rtsp2web 3.2.0 → 3.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/rtsp2web.js CHANGED
@@ -6,4 +6,4 @@
6
6
  * 微信(wechat):miracle421354532
7
7
  * Released under the ISC License.
8
8
  */
9
- "use strict";var e=require("child_process"),t=require("ffmpeg-static"),r=require("http"),n=require("https"),s=require("tls"),i=require("fs");require("util");var o=require("events"),l=require("url"),a=require("base-64"),u=require("ws");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var p=c(e),f=c(t),m=c(r),d=c(n),h=c(s),y=c(i),w=c(o),v=c(l),g=c(a),b=c(u);function O(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function x(e,t,r){return t=T(t),function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(e,C()?Reflect.construct(t,r||[],T(e).constructor):t.apply(e,r))}function S(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function j(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,q(n.key),n)}}function k(e,t,r){return t&&j(e.prototype,t),r&&j(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function M(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=P(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,s=function(){};return{s:s,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:s}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,l=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return o=e.done,e},e:function(e){l=!0,i=e},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw i}}}}function _(e,t,r){return(t=q(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function T(e){return T=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},T(e)}function C(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(C=function(){return!!e})()}function R(e,t){return R=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},R(e,t)}function N(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,s,i,o,l=[],a=!0,u=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;a=!1}else for(;!(a=(n=i.call(r)).done)&&(l.push(n.value),l.length!==t);a=!0);}catch(e){u=!0,s=e}finally{try{if(!a&&null!=r.return&&(o=r.return(),Object(o)!==o))return}finally{if(u)throw s}}return l}}(e,t)||P(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function I(e){return function(e){if(Array.isArray(e))return O(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||P(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function q(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}function A(e){return A="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},A(e)}function P(e,t){if(e){if("string"==typeof e)return O(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?O(e,t):void 0}}var F="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},E={name:"rtsp2web",version:"3.2.0",description:"帮你在web页面中直接播放rtsp视频流,支持同时播放多个",keywords:["rtsp","rtmp","flv","mpeg1video","rtsp2web","media source extensions","ffmpeg"],main:"dist/rtsp2web.js",files:["dist"],scripts:{"node-test":"node test/index.js",pretest:'echo "【start run test directory with pm2】"',test:"npm start",start:"npm run delete-all & pm2 start test/index.js --name rtsp-resource --watch -f",stop:"pm2 stop rtsp-resource",delete:"pm2 delete rtsp-resource",restart:"npm stop && npm run delete && npm start",prebuild:"rimraf dist",build:"rollup -c rollup.config.js","stop-all":"pm2 stop all","delete-all":"pm2 delete all","destroy-all":"npm run stop-all && npm run delete-all",prelist:'echo "---列出当前pm2中的服务---"',list:"pm2 list",monit:"pm2 monit",reload:"pm2 reload all",preexample:'echo "先编译生成构建产物,再使用" ',example:"npm run build && npm run delete-all & pm2 start example/index.js --name rtsp2web -f",prepublish:"npm run build",prelog:'echo "---开始打印日志---"',log:"pm2 log"},repository:{type:"git",url:"https://github.com/NeverYu/rtsp2web.git"},author:{name:"NeverYu",email:"never_yu@qq.com",url:"https://neveryu.github.io"},license:"ISC",bugs:{url:"https://github.com/NeverYu/rtsp2web/issues"},homepage:"https://github.com/NeverYu/rtsp2web#readme",dependencies:{"base-64":"1.0.0","ffmpeg-static":"5.2.0","fluent-ffmpeg":"2.1.3",ws:"^8.5.0"},devDependencies:{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@rollup/plugin-commonjs":"^21.0.3","lodash.camelcase":"^4.3.0",pm2:"^5.2.0",rimraf:"^3.0.2",rollup:"^2.70.1","rollup-plugin-babel":"^4.4.0","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0","rollup-plugin-sourcemaps":"^0.6.3","rollup-plugin-terser":"^7.0.2"}},W=p.default,z=f.default,U=m.default,H=d.default,L=h.default,Q=y.default,Y=w.default,X=v.default,B=g.default.decode,D=b.default.Server,J=E,G=["jsmpeg","flv"],Z="jsmpeg",V={jsmpeg:"mpegts",flv:"flv"},$={jsmpeg:"mpeg1video",flv:"libx264"},K={jsmpeg:"mp2",flv:"aac"},ee=!0,te=18,re=["tcp","udp","udp_multicast","http","https"],ne="",se=!0,ie=!0,oe="drawtext=x=w-tw-5:y=80:fontcolor=white:fontsize=32:text="+decodeURIComponent(B("Y2xlYXIlMjB3aXRoJTIwcXElMjA0MjEzNTQ1MzI="))+":box=1:boxcolor=black,scale=-1:-1,eq=",le=20,ae=10,ue=["-s","-b:v","webplayer","scale","contrast","brightness","saturation","gamma"].concat(["vcodec"]),ce=["scale","contrast","brightness","saturation","gamma"],pe=function(e,t){switch(e){case"-s":if(t.includes("x")&&t.split("x")[0]&&t.split("x")[0]>0&&t.split("x")[1]&&t.split("x")[1]>0)return!0;break;case"vcodec":case"contrast":case"brightness":case"saturation":case"gamma":if(t)return!0;break;case"-b:v":if(t.endsWith("k"))return!0;break;case"webplayer":if(G.includes(t))return!0;break;case"scale":if(t.includes(":")&&t.split(":")[0]&&t.split(":")[1])return!0}},fe=function(){function e(t){var r;return S(this,e),_(r=x(this,e),"exitCode",void 0),_(r,"additionalFlags",[]),_(r,"stream",null),_(r,"webplayer",Z),r.ffmpegPath=z,r.url=t.url,r.ffmpegOptions=t.ffmpegOptions,r.modifyOptions=t.modifyOptions||{},r.options=t,r.initMpeg2Muxer(),r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&R(e,t)}(e,Y.EventEmitter),k(e,[{key:"initMpeg2Muxer",value:function(){var e,t=this;if(se||delete this.ffmpegOptions["-vf"],this.ffmpegOptions.webplayer&&(this.webplayer=this.ffmpegOptions.webplayer,delete this.ffmpegOptions.webplayer),this.ffmpegOptions)for(var r=0,n=Object.entries(this.ffmpegOptions);r<n.length;r++){var s=N(n[r],2),i=s[0],o=s[1];this.additionalFlags.push(i),""!==String(o)&&this.additionalFlags.push(String(o))}(this.spawnOptions=["-use_wallclock_as_timestamps","1","-fflags","nobuffer","-flags","low_delay","-fflags","+discardcorrupt","-thread_queue_size","1024","-i",this.url,"-fps_mode","cfr","-g","10","-r","25","-bf","0","-threads","0","-tune","zerolatency","-c:v",$[this.webplayer],"-crf",te,"-q",te,"-f",V[this.webplayer],"-c:a",K[this.webplayer],ee?"-an":null,ee?null:"-ac",ee?null:"1"].concat(I(this.additionalFlags),["-nostats","-"]),this.modifyOptions.del)&&(null===(e=this.modifyOptions.del)||void 0===e||e.forEach((function(e){var r="-"+e,n=t.spawnOptions.indexOf(r);-1!==n&&(t.spawnOptions[n]=null,n+1<t.spawnOptions.length&&null!==t.spawnOptions[n+1]&&!String(t.spawnOptions[n+1]).startsWith("-")&&(t.spawnOptions[n+1]=null))})));String(ne).length>0&&this.spawnOptions.splice(0,0,"-rtsp_transport",String(ne)),this.spawnOptions=this.spawnOptions.filter((function(e){return null!==e})),console.log("current rtsp's ffmpegOptions: ",this.spawnOptions.join(" ")),this.stream=W.spawn(this.ffmpegPath,this.spawnOptions,{detached:!1}),this.stream.on("error",(function(e){process.stderr.write(" ffmpeg启动时出错,error:"+((null==e?void 0:e.message)||e)+"\n \n")})),this.stream.on("exit",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程退出了; 如果是非正常关闭页面/视频导致的退出, 请检查rtsp2web配置参数代码或联系作者解决.code: "+e+", signal: "+r+" \n \n"),t.emit("exitWithError")})),this.stream.on("close",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程关闭了. code: "+e+", signal: "+r+" \n \n"),t.emit("ffmpegClosed")})),this.stream.stdout.on("data",(function(e){t.emit("mpeg2data",e)})),this.stream.stderr.on("data",(function(e){t.emit("ffmpegStderr",e)}))}}])}(),me=function(){return k((function e(t){S(this,e),_(this,"freeTime",0),_(this,"width",null),_(this,"height",null),_(this,"isStreamWrap",!1),_(this,"_isResetting",!1),_(this,"clients",[]),_(this,"mpeg2Muxer",{instance:null,stream:null,data:null}),_(this,"modifyOptions",{}),this.config=t,this.url=t.url}),[{key:"createStream",value:function(){this.isStreamWrap||(process.stdout.write("[INFO:Channel]create new media stream channel process~ \n"),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new fe({url:this.url,ffmpegOptions:this.formatParams(this.config)}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler())}},{key:"eventHandler",value:function(){var e=this;this.mpeg2Muxer.instance.on("mpeg2data",(function(t){e.broadcast(t)})),this.mpeg2Muxer.instance.on("ffmpegStderr",(function(t){if(t=t.toString(),process.stderr.write("[ERROR]ffmpeg发送的error数据:  \n"),process.stderr.write(t),process.stderr.write("\n"),-1!==t.indexOf("failed")&&(F.process.stdout.write(t+"=== L518 \n"),-1!==t.indexOf("Operation timed out")&&F.process.stdout.write(t+"哎呀~你的链接有问题,超时了!=== L519 \n"),-1===t.indexOf("Conversion")&&-1===t.indexOf("transport")||(console.log("*".concat(ne,"*模式转换失败,请尝试改变transportType的值,然后重试。***")),F.process.stdout.write(t+"=== L520 \n"))),-1!==t.indexOf("404 Not Found")&&F.process.stdout.write(t+"=== L521 \n"),-1!==t.indexOf("Invalid data found")&&F.process.stdout.write(t+"=== L522 \n"),-1!==t.indexOf("Unrecognized option")&&F.process.stdout.write(t+"=== L523 \n"),-1!==t.indexOf("pipe")&&F.process.stdout.write(t+"=== L524 \n"),-1!==t.indexOf("not found")){var r,n;F.process.stdout.write(t+"=== L525 \n");var s=null!==(r=null===(n=t.match(/Option (\w+) not found/))||void 0===n?void 0:n[1])&&void 0!==r?r:"";if("rtsp_transport"===s)return void console.log("--[rtsp2web]请尝试修改 transportType 的值再重试,或者尝试去掉 transportType 再重试--");e.modifyOptions.del?e.modifyOptions.del.push(s):e.modifyOptions.del=[s],e.resetStream()}})),this.mpeg2Muxer.instance.on("exitWithError",(function(){})),this.mpeg2Muxer.instance.on("ffmpegClosed",(function(){e.destroy()}))}},{key:"resetStream",value:function(){var e,t;this._isResetting||(this._isResetting=!0,null===(e=this.mpeg2Muxer.instance)||void 0===e||e.removeAllListeners(),null===(t=this.mpeg2Muxer.stream)||void 0===t||t.kill(),this.mpeg2Muxer.stream=null,this.mpeg2Muxer.instance=null,console.log("[rtsp2web][自动修复]一个视频流转码被自动修复并重启中..."),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new fe({url:this.url,ffmpegOptions:this.formatParams(this.config),modifyOptions:this.modifyOptions}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler(),this._isResetting=!1)}},{key:"formatParams",value:function(e){for(var t={"-vf":oe},r=0,n=Object.entries(e);r<n.length;r++){var s=N(n[r],2),i=s[0],o=s[1];ue.includes(i)&&(ce.includes(i)?"scale"===i?t["-vf"]=t["-vf"].replace(/scale=[x0-9\:\-]*/g,"scale=".concat(o)):t["-vf"]+="".concat(i,"=").concat(o,":"):pe(i,o)&&(t[i]=o))}return t}},{key:"destroy",value:function(){var e,t;null===(e=this.mpeg2Muxer.stream)||void 0===e||e.kill(),this.mpeg2Muxer.stream=null,null===(t=this.mpeg2Muxer.instance)||void 0===t||t.removeAllListeners(),this.mpeg2Muxer.instance=null,this.isStreamWrap=!1,this.dropAllClient()}},{key:"broadcast",value:function(e){var t,r=[],n=M(this.clients);try{for(n.s();!(t=n.n()).done;){var s=t.value;if(s.isSegment)try{s.send(e)}catch(e){r.push(s)}}}catch(e){n.e(e)}finally{n.f()}for(var i=0,o=r;i<o.length;i++){var l=o[i];this.dropClient(l)}}},{key:"addClient",value:function(e){var t=this;e.once("close",(function(){t.dropClient(e)})),this.clients.push(e),this.isStreamWrap||this.createStream(),e.isSegment=!0}},{key:"dropClient",value:function(e){var t=this.clients.indexOf(e);e.isSegment=!1,e.terminate(),e=null,console.log("视频播放窗口关闭1个,销毁一个client(ws句柄)","===L756 \n"),t>-1&&this.clients.splice(t,1)}},{key:"dropAllClient",value:function(){var e,t=M(this.clients);try{for(t.s();!(e=t.n()).done;){var r=e.value;r.isSegment=!1,r.terminate()}}catch(e){t.e(e)}finally{t.f()}this.clients=[]}}])}(),de=function(){return k((function e(t){var r=this;S(this,e),_(this,"channels",new Map),_(this,"_timer",null),_(this,"_server",null),process.stdout.write("【Hello,rtsp2web】[L762]: current rtsp2web version: ".concat(J.version,"; current platform is ").concat(F.process.platform)+"\n");try{Q.chmodSync(z,493)}catch(e){console.log("权限修复跳过:",e.message)}W.execFile(z,["-version"],{windowsHide:!0,stdio:"ignore"},(function(e,t,r){var n,s;e&&(console.log("请检查你的ffmpeg是否正确存在,错误信息:","".concat(e.stack||e.message)),process.exit()),F.process.stdout.write(""+(null!==(n=null===(s=t.match(/ffmpeg version\s+(\S+)/))||void 0===s?void 0:s[0])&&void 0!==n?n:"ffmpeg version info not available")+"\n")})),t&&"boolean"==typeof t.wm1&&!t.wm1&&(oe="scale=-1:-1,eq=",ie=!1),t&&"boolean"==typeof t.vf1&&!t.vf1&&(se=!1),t&&"string"==typeof t.webplayer&&G.includes(t.webplayer)&&(Z=t.webplayer),t&&"number"==typeof t.q&&t.q>=0&&(te=t.q),t&&"string"==typeof t.transportType&&re.includes(t.transportType)&&(ne=t.transportType),t&&"boolean"==typeof t.audio&&(ee=!t.audio),t&&"number"==typeof t.freeTime&&!isNaN(t.freeTime)&&(le=t.freeTime>=3?parseInt(t.freeTime,10):3),t&&"number"==typeof t.checkTime&&!isNaN(t.checkTime)&&(ae=t.checkTime>=2?parseInt(t.checkTime,10):2),this._timer=setInterval((function(){r.checkFree(),ie&&(oe.includes(decodeURIComponent(B("eCUzRHctdHctNSUzQXklM0Q4MCUzQWZvbnRjb2xvciUzRHdoaXRlJTNBZm9udHNpemUlM0QzMiUzQXRleHQlM0RjbGVhciUyMHdpdGglMjBxcSUyMDQyMTM1NDUzMiUzQWJveCUzRDElM0Fib3hjb2xvciUzRGJsYWNr")))||(r.destroyAllChannel(),F.process.stderr.write("wm代码异常、视频闪屏的问题,请联系作者帮你解决! \n")))}),1e3*ae);var n=U.createServer((function(e,t){t.writeHead(200),t.end("hello rtsp2web, with ws [ws] model ~ \n")}));if(t&&"object"===A(t.wss))if(process.stderr.write("wss启动中... \n"),t.wss.hasOwnProperty("pfx"))if(t.wss.hasOwnProperty("passphrase"))try{n=H.createServer({pfx:Q.readFileSync(t.wss.pfx),passphrase:Q.readFileSync(t.wss.passphrase)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [pfx&passphrase] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取pfx安全证书文件出错, wss启动失败了, 已切换到ws模式~ 请检查你的wss配置(pfx字段和passphrase自带),错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请你传入正确的密码文件路径参数:passphrase \n"),F.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else if(t.wss.hasOwnProperty("cert"))if(t.wss.hasOwnProperty("key"))try{n=H.createServer({key:Q.readFileSync(t.wss.key),cert:Q.readFileSync(t.wss.cert)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [key&cert] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取SSL证书文件出错, wss启动失败了, 请检查你的wss配置(key字段和cert自带), 错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书私钥文件(key.pem)的路径 \n"),F.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书公钥文件(cert.pem)的路径 \n"),F.process.stdout.write("[INFO]正在为你切换到ws模式... \n");n.listen(t&&t.port||9999),this._server=n,Object.getPrototypeOf(n)instanceof L.Server?process.stdout.write("[INFO L1013]currently in wss model \n"):process.stdout.write("[INFO L1015]currently in ws model \n"),this.wss=new D({server:n}),this.wss.on("connection",(function(e,t){var n=X.parse(t.url,!0);if(n.query.url){var s=B(n.query.url.toString());n.query.url=s,r.registeClient(e,{url:s,options:n.query}),console.log("一个新的视频播放窗口(client,ws句柄)连接成功,请等待画面...")}else console.log("[rtsp2web] 收到无 url 参数的 WebSocket 连接,已拒绝"),e.close(1008,"missing url parameter")}))}),[{key:"registeClient",value:function(e,t){var r,n=this.getChannel(t.url);n||(n=this.createChannel(t.options,e)),null===(r=n)||void 0===r||r.addClient(e)}},{key:"getChannel",value:function(e){var t;return null!==(t=this.channels.get(e))&&void 0!==t?t:null}},{key:"createChannel",value:function(e,t){var r=new me(e,t);return this.channels.set(r.url,r),r}},{key:"checkFree",value:function(){var e,t=M(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;r.clients.length>0?r.freeTime=0:r.freeTime+=ae,r.freeTime>=le&&this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroyChannel",value:function(e){this.channels.delete(e.url)&&e.destroy()}},{key:"destroyAllChannel",value:function(){var e,t=M(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroy",value:function(){if(this._timer&&(clearInterval(this._timer),this._timer=null),this.destroyAllChannel(),this.wss)try{this.wss.close(),this.wss=null}catch(e){console.log("[rtsp2web] 关闭 WebSocket 服务器时出错:",e.message)}if(this._server)try{this._server.close(),this._server=null}catch(e){console.log("[rtsp2web] 关闭 HTTP 服务器时出错:",e.message)}}}])}();module.exports=de;
9
+ "use strict";var e=require("child_process"),t=require("ffmpeg-static"),r=require("http"),n=require("https"),s=require("tls"),i=require("fs");require("util");var o=require("events"),l=require("url"),a=require("ws");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var c=u(e),p=u(t),f=u(r),m=u(n),d=u(s),h=u(i),y=u(o),w=u(l),v=u(a);function g(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function b(e,t,r){return t=M(t),function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(e,_()?Reflect.construct(t,r||[],M(e).constructor):t.apply(e,r))}function O(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function x(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,N(n.key),n)}}function S(e,t,r){return t&&x(e.prototype,t),r&&x(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function j(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=q(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,s=function(){};return{s:s,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:s}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,l=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return o=e.done,e},e:function(e){l=!0,i=e},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw i}}}}function k(e,t,r){return(t=N(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function M(e){return M=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},M(e)}function _(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(_=function(){return!!e})()}function T(e,t){return T=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},T(e,t)}function C(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,s,i,o,l=[],a=!0,u=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;a=!1}else for(;!(a=(n=i.call(r)).done)&&(l.push(n.value),l.length!==t);a=!0);}catch(e){u=!0,s=e}finally{try{if(!a&&null!=r.return&&(o=r.return(),Object(o)!==o))return}finally{if(u)throw s}}return l}}(e,t)||q(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function R(e){return function(e){if(Array.isArray(e))return g(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||q(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function N(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}function I(e){return I="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},I(e)}function q(e,t){if(e){if("string"==typeof e)return g(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?g(e,t):void 0}}var A="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},P={name:"rtsp2web",version:"3.2.0",description:"帮你在web页面中直接播放rtsp视频流,支持同时播放多个",keywords:["rtsp","rtmp","flv","mpeg1video","rtsp2web","media source extensions","ffmpeg"],main:"dist/rtsp2web.js",files:["dist"],scripts:{"node-test":"node test/index.js",pretest:'echo "【start run test directory with pm2】"',test:"npm start",start:"npm run delete-all & pm2 start test/index.js --name rtsp-resource --watch -f",stop:"pm2 stop rtsp-resource",delete:"pm2 delete rtsp-resource",restart:"npm stop && npm run delete && npm start",prebuild:"rimraf dist",build:"rollup -c rollup.config.js","stop-all":"pm2 stop all","delete-all":"pm2 delete all","destroy-all":"npm run stop-all && npm run delete-all",prelist:'echo "---列出当前pm2中的服务---"',list:"pm2 list",monit:"pm2 monit",reload:"pm2 reload all",preexample:'echo "先编译生成构建产物,再使用" ',example:"npm run build && npm run delete-all & pm2 start example/index.js --name rtsp2web -f",prepublish:"npm run build",prelog:'echo "---开始打印日志---"',log:"pm2 log"},repository:{type:"git",url:"https://github.com/NeverYu/rtsp2web.git"},author:{name:"NeverYu",email:"never_yu@qq.com",url:"https://neveryu.github.io"},license:"ISC",bugs:{url:"https://github.com/NeverYu/rtsp2web/issues"},homepage:"https://github.com/NeverYu/rtsp2web#readme",dependencies:{"ffmpeg-static":"5.2.0",ws:"8.21.0"},devDependencies:{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@rollup/plugin-commonjs":"^21.0.3","lodash.camelcase":"^4.3.0",pm2:"^5.2.0",rimraf:"^3.0.2",rollup:"^2.70.1","rollup-plugin-babel":"^4.4.0","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0","rollup-plugin-sourcemaps":"^0.6.3","rollup-plugin-terser":"^7.0.2"}},F=c.default,E=p.default,W=f.default,z=m.default,L=d.default,U=h.default,H=y.default,Q=w.default,Y=v.default.Server,B=P,X=function(e){return Buffer.from(e,"base64").toString("utf8")},D=["jsmpeg","flv"],J="jsmpeg",G={jsmpeg:"mpegts",flv:"flv"},Z={jsmpeg:"mpeg1video",flv:"libx264"},V={jsmpeg:"mp2",flv:"aac"},$=!0,K=18,ee=["tcp","udp","udp_multicast","http","https"],te="",re=!0,ne=!0,se="drawtext=x=w-tw-5:y=80:fontcolor=white:fontsize=32:text="+decodeURIComponent(X("Y2xlYXIlMjB3aXRoJTIwcXElMjA0MjEzNTQ1MzI="))+":box=1:boxcolor=black,scale=-1:-1,eq=",ie=20,oe=10,le=["-s","-b:v","webplayer","scale","contrast","brightness","saturation","gamma"].concat(["vcodec"]),ae=["scale","contrast","brightness","saturation","gamma"],ue=function(e,t){switch(e){case"-s":if(t.includes("x")&&t.split("x")[0]&&t.split("x")[0]>0&&t.split("x")[1]&&t.split("x")[1]>0)return!0;break;case"vcodec":case"contrast":case"brightness":case"saturation":case"gamma":if(t)return!0;break;case"-b:v":if(t.endsWith("k"))return!0;break;case"webplayer":if(D.includes(t))return!0;break;case"scale":if(t.includes(":")&&t.split(":")[0]&&t.split(":")[1])return!0}},ce=function(){function e(t){var r;return O(this,e),k(r=b(this,e),"exitCode",void 0),k(r,"additionalFlags",[]),k(r,"stream",null),k(r,"webplayer",J),r.ffmpegPath=E,r.url=t.url,r.ffmpegOptions=t.ffmpegOptions,r.modifyOptions=t.modifyOptions||{},r.options=t,r.initMpeg2Muxer(),r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&T(e,t)}(e,H.EventEmitter),S(e,[{key:"initMpeg2Muxer",value:function(){var e,t=this;if(re||delete this.ffmpegOptions["-vf"],this.ffmpegOptions.webplayer&&(this.webplayer=this.ffmpegOptions.webplayer,delete this.ffmpegOptions.webplayer),this.ffmpegOptions)for(var r=0,n=Object.entries(this.ffmpegOptions);r<n.length;r++){var s=C(n[r],2),i=s[0],o=s[1];this.additionalFlags.push(i),""!==String(o)&&this.additionalFlags.push(String(o))}(this.spawnOptions=["-use_wallclock_as_timestamps","1","-fflags","nobuffer","-flags","low_delay","-fflags","+discardcorrupt","-thread_queue_size","1024","-i",this.url,"-fps_mode","cfr","-g","10","-r","25","-bf","0","-threads","0","-tune","zerolatency","-c:v",Z[this.webplayer],"-crf",K,"-q",K,"-f",G[this.webplayer],"-c:a",V[this.webplayer],$?"-an":null,$?null:"-ac",$?null:"1"].concat(R(this.additionalFlags),["-nostats","-"]),this.modifyOptions.del)&&(null===(e=this.modifyOptions.del)||void 0===e||e.forEach((function(e){var r="-"+e,n=t.spawnOptions.indexOf(r);-1!==n&&(t.spawnOptions[n]=null,n+1<t.spawnOptions.length&&null!==t.spawnOptions[n+1]&&!String(t.spawnOptions[n+1]).startsWith("-")&&(t.spawnOptions[n+1]=null))})));String(te).length>0&&this.spawnOptions.splice(0,0,"-rtsp_transport",String(te)),this.spawnOptions=this.spawnOptions.filter((function(e){return null!==e})),console.log("current rtsp's ffmpegOptions: ",this.spawnOptions.join(" ")),this.stream=F.spawn(this.ffmpegPath,this.spawnOptions,{detached:!1}),this.stream.on("error",(function(e){process.stderr.write(" ffmpeg启动时出错,error:"+((null==e?void 0:e.message)||e)+"\n \n")})),this.stream.on("exit",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程退出了; 如果是非正常关闭页面/视频导致的退出, 请检查rtsp2web配置参数代码或联系作者解决.code: "+e+", signal: "+r+" \n \n"),t.emit("exitWithError")})),this.stream.on("close",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程关闭了. code: "+e+", signal: "+r+" \n \n"),t.emit("ffmpegClosed")})),this.stream.stdout.on("data",(function(e){t.emit("mpeg2data",e)})),this.stream.stderr.on("data",(function(e){t.emit("ffmpegStderr",e)}))}}])}(),pe=function(){return S((function e(t){O(this,e),k(this,"freeTime",0),k(this,"width",null),k(this,"height",null),k(this,"isStreamWrap",!1),k(this,"_isResetting",!1),k(this,"clients",[]),k(this,"mpeg2Muxer",{instance:null,stream:null,data:null}),k(this,"modifyOptions",{}),this.config=t,this.url=t.url}),[{key:"createStream",value:function(){this.isStreamWrap||(process.stdout.write("[INFO:Channel]create new media stream channel process~ \n"),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new ce({url:this.url,ffmpegOptions:this.formatParams(this.config)}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler())}},{key:"eventHandler",value:function(){var e=this;this.mpeg2Muxer.instance.on("mpeg2data",(function(t){e.broadcast(t)})),this.mpeg2Muxer.instance.on("ffmpegStderr",(function(t){if(t=t.toString(),process.stderr.write("[ERROR]ffmpeg发送的error数据:  \n"),process.stderr.write(t),process.stderr.write("\n"),-1!==t.indexOf("failed")&&(A.process.stdout.write(t+"=== L518 \n"),-1!==t.indexOf("Operation timed out")&&A.process.stdout.write(t+"哎呀~你的链接有问题,超时了!=== L519 \n"),-1===t.indexOf("Conversion")&&-1===t.indexOf("transport")||(console.log("*".concat(te,"*模式转换失败,请尝试改变transportType的值,然后重试。***")),A.process.stdout.write(t+"=== L520 \n"))),-1!==t.indexOf("404 Not Found")&&A.process.stdout.write(t+"=== L521 \n"),-1!==t.indexOf("Invalid data found")&&A.process.stdout.write(t+"=== L522 \n"),-1!==t.indexOf("Unrecognized option")&&A.process.stdout.write(t+"=== L523 \n"),-1!==t.indexOf("pipe")&&A.process.stdout.write(t+"=== L524 \n"),-1!==t.indexOf("not found")){var r,n;A.process.stdout.write(t+"=== L525 \n");var s=null!==(r=null===(n=t.match(/Option (\w+) not found/))||void 0===n?void 0:n[1])&&void 0!==r?r:"";if("rtsp_transport"===s)return void console.log("--[rtsp2web]请尝试修改 transportType 的值再重试,或者尝试去掉 transportType 再重试--");e.modifyOptions.del?e.modifyOptions.del.push(s):e.modifyOptions.del=[s],e.resetStream()}})),this.mpeg2Muxer.instance.on("exitWithError",(function(){})),this.mpeg2Muxer.instance.on("ffmpegClosed",(function(){e.destroy()}))}},{key:"resetStream",value:function(){var e,t;this._isResetting||(this._isResetting=!0,null===(e=this.mpeg2Muxer.instance)||void 0===e||e.removeAllListeners(),null===(t=this.mpeg2Muxer.stream)||void 0===t||t.kill(),this.mpeg2Muxer.stream=null,this.mpeg2Muxer.instance=null,console.log("[rtsp2web][自动修复]一个视频流转码被自动修复并重启中..."),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new ce({url:this.url,ffmpegOptions:this.formatParams(this.config),modifyOptions:this.modifyOptions}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler(),this._isResetting=!1)}},{key:"formatParams",value:function(e){for(var t={"-vf":se},r=0,n=Object.entries(e);r<n.length;r++){var s=C(n[r],2),i=s[0],o=s[1];le.includes(i)&&(ae.includes(i)?"scale"===i?t["-vf"]=t["-vf"].replace(/scale=[x0-9\:\-]*/g,"scale=".concat(o)):t["-vf"]+="".concat(i,"=").concat(o,":"):ue(i,o)&&(t[i]=o))}return t}},{key:"destroy",value:function(){var e,t;null===(e=this.mpeg2Muxer.stream)||void 0===e||e.kill(),this.mpeg2Muxer.stream=null,null===(t=this.mpeg2Muxer.instance)||void 0===t||t.removeAllListeners(),this.mpeg2Muxer.instance=null,this.isStreamWrap=!1,this.dropAllClient()}},{key:"broadcast",value:function(e){var t,r=[],n=j(this.clients);try{for(n.s();!(t=n.n()).done;){var s=t.value;if(s.isSegment)try{s.send(e)}catch(e){r.push(s)}}}catch(e){n.e(e)}finally{n.f()}for(var i=0,o=r;i<o.length;i++){var l=o[i];this.dropClient(l)}}},{key:"addClient",value:function(e){var t=this;e.once("close",(function(){t.dropClient(e)})),this.clients.push(e),this.isStreamWrap||this.createStream(),e.isSegment=!0}},{key:"dropClient",value:function(e){var t=this.clients.indexOf(e);e.isSegment=!1,e.terminate(),e=null,console.log("视频播放窗口关闭1个,销毁一个client(ws句柄)","===L756 \n"),t>-1&&this.clients.splice(t,1)}},{key:"dropAllClient",value:function(){var e,t=j(this.clients);try{for(t.s();!(e=t.n()).done;){var r=e.value;r.isSegment=!1,r.terminate()}}catch(e){t.e(e)}finally{t.f()}this.clients=[]}}])}(),fe=function(){return S((function e(t){var r=this;O(this,e),k(this,"channels",new Map),k(this,"_timer",null),k(this,"_server",null),process.stdout.write("【Hello,rtsp2web】[L762]: current rtsp2web version: ".concat(B.version,"; current platform is ").concat(A.process.platform)+"\n");try{U.chmodSync(E,493)}catch(e){console.log("权限修复跳过:",e.message)}F.execFile(E,["-version"],{windowsHide:!0,stdio:"ignore"},(function(e,t,r){var n,s;e&&(console.log("请检查你的ffmpeg是否正确存在,错误信息:","".concat(e.stack||e.message)),process.exit()),A.process.stdout.write(""+(null!==(n=null===(s=t.match(/ffmpeg version\s+(\S+)/))||void 0===s?void 0:s[0])&&void 0!==n?n:"ffmpeg version info not available")+"\n")})),t&&"boolean"==typeof t.wm1&&!t.wm1&&(se="scale=-1:-1,eq=",ne=!1),t&&"boolean"==typeof t.vf1&&!t.vf1&&(re=!1),t&&"string"==typeof t.webplayer&&D.includes(t.webplayer)&&(J=t.webplayer),t&&"number"==typeof t.q&&t.q>=0&&(K=t.q),t&&"string"==typeof t.transportType&&ee.includes(t.transportType)&&(te=t.transportType),t&&"boolean"==typeof t.audio&&($=!t.audio),t&&"number"==typeof t.freeTime&&!isNaN(t.freeTime)&&(ie=t.freeTime>=3?parseInt(t.freeTime,10):3),t&&"number"==typeof t.checkTime&&!isNaN(t.checkTime)&&(oe=t.checkTime>=2?parseInt(t.checkTime,10):2),this._timer=setInterval((function(){r.checkFree(),ne&&(se.includes(decodeURIComponent(X("eCUzRHctdHctNSUzQXklM0Q4MCUzQWZvbnRjb2xvciUzRHdoaXRlJTNBZm9udHNpemUlM0QzMiUzQXRleHQlM0RjbGVhciUyMHdpdGglMjBxcSUyMDQyMTM1NDUzMiUzQWJveCUzRDElM0Fib3hjb2xvciUzRGJsYWNr")))||(r.destroyAllChannel(),A.process.stderr.write("wm代码异常、视频闪屏的问题,请联系作者帮你解决! \n")))}),1e3*oe);var n=W.createServer((function(e,t){t.writeHead(200),t.end("hello rtsp2web, with ws [ws] model ~ \n")}));if(t&&"object"===I(t.wss))if(process.stderr.write("wss启动中... \n"),t.wss.hasOwnProperty("pfx"))if(t.wss.hasOwnProperty("passphrase"))try{n=z.createServer({pfx:U.readFileSync(t.wss.pfx),passphrase:U.readFileSync(t.wss.passphrase)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [pfx&passphrase] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取pfx安全证书文件出错, wss启动失败了, 已切换到ws模式~ 请检查你的wss配置(pfx字段和passphrase自带),错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请你传入正确的密码文件路径参数:passphrase \n"),A.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else if(t.wss.hasOwnProperty("cert"))if(t.wss.hasOwnProperty("key"))try{n=z.createServer({key:U.readFileSync(t.wss.key),cert:U.readFileSync(t.wss.cert)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [key&cert] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取SSL证书文件出错, wss启动失败了, 请检查你的wss配置(key字段和cert自带), 错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书私钥文件(key.pem)的路径 \n"),A.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书公钥文件(cert.pem)的路径 \n"),A.process.stdout.write("[INFO]正在为你切换到ws模式... \n");n.listen(t&&t.port||9999),this._server=n,Object.getPrototypeOf(n)instanceof L.Server?process.stdout.write("[INFO L1013]currently in wss model \n"):process.stdout.write("[INFO L1015]currently in ws model \n"),this.wss=new Y({server:n}),this.wss.on("connection",(function(e,t){var n=Q.parse(t.url,!0);if(n.query.url){var s=X(n.query.url.toString());n.query.url=s,r.registeClient(e,{url:s,options:n.query}),console.log("一个新的视频播放窗口(client,ws句柄)连接成功,请等待画面...")}else console.log("[rtsp2web L1051] 收到无 url 参数的 WebSocket 连接,已拒绝"),e.close(1008,"missing url parameter")}))}),[{key:"registeClient",value:function(e,t){var r,n=this.getChannel(t.url);n||(n=this.createChannel(t.options,e)),null===(r=n)||void 0===r||r.addClient(e)}},{key:"getChannel",value:function(e){var t;return null!==(t=this.channels.get(e))&&void 0!==t?t:null}},{key:"createChannel",value:function(e,t){var r=new pe(e,t);return this.channels.set(r.url,r),r}},{key:"checkFree",value:function(){var e,t=j(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;r.clients.length>0?r.freeTime=0:r.freeTime+=oe,r.freeTime>=ie&&this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroyChannel",value:function(e){this.channels.delete(e.url)&&e.destroy()}},{key:"destroyAllChannel",value:function(){var e,t=j(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroy",value:function(){if(this._timer&&(clearInterval(this._timer),this._timer=null),this.destroyAllChannel(),this.wss)try{this.wss.close(),this.wss=null}catch(e){console.log("[rtsp2web] 关闭 WebSocket 服务器时出错:",e.message)}if(this._server)try{this._server.close(),this._server=null}catch(e){console.log("[rtsp2web] 关闭 HTTP 服务器时出错:",e.message)}}}])}();module.exports=fe;
@@ -6,4 +6,4 @@
6
6
  * 微信(wechat):miracle421354532
7
7
  * Released under the ISC License.
8
8
  */
9
- "use strict";var e=require("child_process"),t=require("ffmpeg-static"),r=require("http"),n=require("https"),s=require("tls"),i=require("fs");require("util");var o=require("events"),l=require("url"),a=require("base-64"),u=require("ws");function c(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var p=c(e),f=c(t),m=c(r),d=c(n),h=c(s),y=c(i),w=c(o),v=c(l),g=c(a),b=c(u);function O(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function x(e,t,r){return t=T(t),function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(e,C()?Reflect.construct(t,r||[],T(e).constructor):t.apply(e,r))}function S(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function j(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,q(n.key),n)}}function k(e,t,r){return t&&j(e.prototype,t),r&&j(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function M(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=P(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,s=function(){};return{s:s,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:s}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,l=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return o=e.done,e},e:function(e){l=!0,i=e},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw i}}}}function _(e,t,r){return(t=q(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function T(e){return T=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},T(e)}function C(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(C=function(){return!!e})()}function R(e,t){return R=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},R(e,t)}function N(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,s,i,o,l=[],a=!0,u=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;a=!1}else for(;!(a=(n=i.call(r)).done)&&(l.push(n.value),l.length!==t);a=!0);}catch(e){u=!0,s=e}finally{try{if(!a&&null!=r.return&&(o=r.return(),Object(o)!==o))return}finally{if(u)throw s}}return l}}(e,t)||P(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function I(e){return function(e){if(Array.isArray(e))return O(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||P(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function q(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}function A(e){return A="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},A(e)}function P(e,t){if(e){if("string"==typeof e)return O(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?O(e,t):void 0}}var F="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},E={name:"rtsp2web",version:"3.2.0",description:"帮你在web页面中直接播放rtsp视频流,支持同时播放多个",keywords:["rtsp","rtmp","flv","mpeg1video","rtsp2web","media source extensions","ffmpeg"],main:"dist/rtsp2web.js",files:["dist"],scripts:{"node-test":"node test/index.js",pretest:'echo "【start run test directory with pm2】"',test:"npm start",start:"npm run delete-all & pm2 start test/index.js --name rtsp-resource --watch -f",stop:"pm2 stop rtsp-resource",delete:"pm2 delete rtsp-resource",restart:"npm stop && npm run delete && npm start",prebuild:"rimraf dist",build:"rollup -c rollup.config.js","stop-all":"pm2 stop all","delete-all":"pm2 delete all","destroy-all":"npm run stop-all && npm run delete-all",prelist:'echo "---列出当前pm2中的服务---"',list:"pm2 list",monit:"pm2 monit",reload:"pm2 reload all",preexample:'echo "先编译生成构建产物,再使用" ',example:"npm run build && npm run delete-all & pm2 start example/index.js --name rtsp2web -f",prepublish:"npm run build",prelog:'echo "---开始打印日志---"',log:"pm2 log"},repository:{type:"git",url:"https://github.com/NeverYu/rtsp2web.git"},author:{name:"NeverYu",email:"never_yu@qq.com",url:"https://neveryu.github.io"},license:"ISC",bugs:{url:"https://github.com/NeverYu/rtsp2web/issues"},homepage:"https://github.com/NeverYu/rtsp2web#readme",dependencies:{"base-64":"1.0.0","ffmpeg-static":"5.2.0","fluent-ffmpeg":"2.1.3",ws:"^8.5.0"},devDependencies:{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@rollup/plugin-commonjs":"^21.0.3","lodash.camelcase":"^4.3.0",pm2:"^5.2.0",rimraf:"^3.0.2",rollup:"^2.70.1","rollup-plugin-babel":"^4.4.0","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0","rollup-plugin-sourcemaps":"^0.6.3","rollup-plugin-terser":"^7.0.2"}},W=p.default,z=f.default,U=m.default,H=d.default,L=h.default,Q=y.default,Y=w.default,X=v.default,B=g.default.decode,D=b.default.Server,J=E,G=["jsmpeg","flv"],Z="jsmpeg",V={jsmpeg:"mpegts",flv:"flv"},$={jsmpeg:"mpeg1video",flv:"libx264"},K={jsmpeg:"mp2",flv:"aac"},ee=!0,te=18,re=["tcp","udp","udp_multicast","http","https"],ne="",se=!0,ie=!0,oe="drawtext=x=w-tw-5:y=80:fontcolor=white:fontsize=32:text="+decodeURIComponent(B("Y2xlYXIlMjB3aXRoJTIwcXElMjA0MjEzNTQ1MzI="))+":box=1:boxcolor=black,scale=-1:-1,eq=",le=20,ae=10,ue=["-s","-b:v","webplayer","scale","contrast","brightness","saturation","gamma"].concat(["vcodec"]),ce=["scale","contrast","brightness","saturation","gamma"],pe=function(e,t){switch(e){case"-s":if(t.includes("x")&&t.split("x")[0]&&t.split("x")[0]>0&&t.split("x")[1]&&t.split("x")[1]>0)return!0;break;case"vcodec":case"contrast":case"brightness":case"saturation":case"gamma":if(t)return!0;break;case"-b:v":if(t.endsWith("k"))return!0;break;case"webplayer":if(G.includes(t))return!0;break;case"scale":if(t.includes(":")&&t.split(":")[0]&&t.split(":")[1])return!0}},fe=function(){function e(t){var r;return S(this,e),_(r=x(this,e),"exitCode",void 0),_(r,"additionalFlags",[]),_(r,"stream",null),_(r,"webplayer",Z),r.ffmpegPath=z,r.url=t.url,r.ffmpegOptions=t.ffmpegOptions,r.modifyOptions=t.modifyOptions||{},r.options=t,r.initMpeg2Muxer(),r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&R(e,t)}(e,Y.EventEmitter),k(e,[{key:"initMpeg2Muxer",value:function(){var e,t=this;if(se||delete this.ffmpegOptions["-vf"],this.ffmpegOptions.webplayer&&(this.webplayer=this.ffmpegOptions.webplayer,delete this.ffmpegOptions.webplayer),this.ffmpegOptions)for(var r=0,n=Object.entries(this.ffmpegOptions);r<n.length;r++){var s=N(n[r],2),i=s[0],o=s[1];this.additionalFlags.push(i),""!==String(o)&&this.additionalFlags.push(String(o))}(this.spawnOptions=["-use_wallclock_as_timestamps","1","-fflags","nobuffer","-flags","low_delay","-fflags","+discardcorrupt","-thread_queue_size","1024","-i",this.url,"-fps_mode","cfr","-g","10","-r","25","-bf","0","-threads","0","-tune","zerolatency","-c:v",$[this.webplayer],"-crf",te,"-q",te,"-f",V[this.webplayer],"-c:a",K[this.webplayer],ee?"-an":null,ee?null:"-ac",ee?null:"1"].concat(I(this.additionalFlags),["-nostats","-"]),this.modifyOptions.del)&&(null===(e=this.modifyOptions.del)||void 0===e||e.forEach((function(e){var r="-"+e,n=t.spawnOptions.indexOf(r);-1!==n&&(t.spawnOptions[n]=null,n+1<t.spawnOptions.length&&null!==t.spawnOptions[n+1]&&!String(t.spawnOptions[n+1]).startsWith("-")&&(t.spawnOptions[n+1]=null))})));String(ne).length>0&&this.spawnOptions.splice(0,0,"-rtsp_transport",String(ne)),this.spawnOptions=this.spawnOptions.filter((function(e){return null!==e})),console.log("current rtsp's ffmpegOptions: ",this.spawnOptions.join(" ")),this.stream=W.spawn(this.ffmpegPath,this.spawnOptions,{detached:!1}),this.stream.on("error",(function(e){process.stderr.write(" ffmpeg启动时出错,error:"+((null==e?void 0:e.message)||e)+"\n \n")})),this.stream.on("exit",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程退出了; 如果是非正常关闭页面/视频导致的退出, 请检查rtsp2web配置参数代码或联系作者解决.code: "+e+", signal: "+r+" \n \n"),t.emit("exitWithError")})),this.stream.on("close",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程关闭了. code: "+e+", signal: "+r+" \n \n"),t.emit("ffmpegClosed")})),this.stream.stdout.on("data",(function(e){t.emit("mpeg2data",e)})),this.stream.stderr.on("data",(function(e){t.emit("ffmpegStderr",e)}))}}])}(),me=function(){return k((function e(t){S(this,e),_(this,"freeTime",0),_(this,"width",null),_(this,"height",null),_(this,"isStreamWrap",!1),_(this,"_isResetting",!1),_(this,"clients",[]),_(this,"mpeg2Muxer",{instance:null,stream:null,data:null}),_(this,"modifyOptions",{}),this.config=t,this.url=t.url}),[{key:"createStream",value:function(){this.isStreamWrap||(process.stdout.write("[INFO:Channel]create new media stream channel process~ \n"),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new fe({url:this.url,ffmpegOptions:this.formatParams(this.config)}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler())}},{key:"eventHandler",value:function(){var e=this;this.mpeg2Muxer.instance.on("mpeg2data",(function(t){e.broadcast(t)})),this.mpeg2Muxer.instance.on("ffmpegStderr",(function(t){if(t=t.toString(),process.stderr.write("[ERROR]ffmpeg发送的error数据:  \n"),process.stderr.write(t),process.stderr.write("\n"),-1!==t.indexOf("failed")&&(F.process.stdout.write(t+"=== L518 \n"),-1!==t.indexOf("Operation timed out")&&F.process.stdout.write(t+"哎呀~你的链接有问题,超时了!=== L519 \n"),-1===t.indexOf("Conversion")&&-1===t.indexOf("transport")||(console.log("*".concat(ne,"*模式转换失败,请尝试改变transportType的值,然后重试。***")),F.process.stdout.write(t+"=== L520 \n"))),-1!==t.indexOf("404 Not Found")&&F.process.stdout.write(t+"=== L521 \n"),-1!==t.indexOf("Invalid data found")&&F.process.stdout.write(t+"=== L522 \n"),-1!==t.indexOf("Unrecognized option")&&F.process.stdout.write(t+"=== L523 \n"),-1!==t.indexOf("pipe")&&F.process.stdout.write(t+"=== L524 \n"),-1!==t.indexOf("not found")){var r,n;F.process.stdout.write(t+"=== L525 \n");var s=null!==(r=null===(n=t.match(/Option (\w+) not found/))||void 0===n?void 0:n[1])&&void 0!==r?r:"";if("rtsp_transport"===s)return void console.log("--[rtsp2web]请尝试修改 transportType 的值再重试,或者尝试去掉 transportType 再重试--");e.modifyOptions.del?e.modifyOptions.del.push(s):e.modifyOptions.del=[s],e.resetStream()}})),this.mpeg2Muxer.instance.on("exitWithError",(function(){})),this.mpeg2Muxer.instance.on("ffmpegClosed",(function(){e.destroy()}))}},{key:"resetStream",value:function(){var e,t;this._isResetting||(this._isResetting=!0,null===(e=this.mpeg2Muxer.instance)||void 0===e||e.removeAllListeners(),null===(t=this.mpeg2Muxer.stream)||void 0===t||t.kill(),this.mpeg2Muxer.stream=null,this.mpeg2Muxer.instance=null,console.log("[rtsp2web][自动修复]一个视频流转码被自动修复并重启中..."),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new fe({url:this.url,ffmpegOptions:this.formatParams(this.config),modifyOptions:this.modifyOptions}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler(),this._isResetting=!1)}},{key:"formatParams",value:function(e){for(var t={"-vf":oe},r=0,n=Object.entries(e);r<n.length;r++){var s=N(n[r],2),i=s[0],o=s[1];ue.includes(i)&&(ce.includes(i)?"scale"===i?t["-vf"]=t["-vf"].replace(/scale=[x0-9\:\-]*/g,"scale=".concat(o)):t["-vf"]+="".concat(i,"=").concat(o,":"):pe(i,o)&&(t[i]=o))}return t}},{key:"destroy",value:function(){var e,t;null===(e=this.mpeg2Muxer.stream)||void 0===e||e.kill(),this.mpeg2Muxer.stream=null,null===(t=this.mpeg2Muxer.instance)||void 0===t||t.removeAllListeners(),this.mpeg2Muxer.instance=null,this.isStreamWrap=!1,this.dropAllClient()}},{key:"broadcast",value:function(e){var t,r=[],n=M(this.clients);try{for(n.s();!(t=n.n()).done;){var s=t.value;if(s.isSegment)try{s.send(e)}catch(e){r.push(s)}}}catch(e){n.e(e)}finally{n.f()}for(var i=0,o=r;i<o.length;i++){var l=o[i];this.dropClient(l)}}},{key:"addClient",value:function(e){var t=this;e.once("close",(function(){t.dropClient(e)})),this.clients.push(e),this.isStreamWrap||this.createStream(),e.isSegment=!0}},{key:"dropClient",value:function(e){var t=this.clients.indexOf(e);e.isSegment=!1,e.terminate(),e=null,console.log("视频播放窗口关闭1个,销毁一个client(ws句柄)","===L756 \n"),t>-1&&this.clients.splice(t,1)}},{key:"dropAllClient",value:function(){var e,t=M(this.clients);try{for(t.s();!(e=t.n()).done;){var r=e.value;r.isSegment=!1,r.terminate()}}catch(e){t.e(e)}finally{t.f()}this.clients=[]}}])}(),de=function(){return k((function e(t){var r=this;S(this,e),_(this,"channels",new Map),_(this,"_timer",null),_(this,"_server",null),process.stdout.write("【Hello,rtsp2web】[L762]: current rtsp2web version: ".concat(J.version,"; current platform is ").concat(F.process.platform)+"\n");try{Q.chmodSync(z,493)}catch(e){console.log("权限修复跳过:",e.message)}W.execFile(z,["-version"],{windowsHide:!0,stdio:"ignore"},(function(e,t,r){var n,s;e&&(console.log("请检查你的ffmpeg是否正确存在,错误信息:","".concat(e.stack||e.message)),process.exit()),F.process.stdout.write(""+(null!==(n=null===(s=t.match(/ffmpeg version\s+(\S+)/))||void 0===s?void 0:s[0])&&void 0!==n?n:"ffmpeg version info not available")+"\n")})),t&&"boolean"==typeof t.wm1&&!t.wm1&&(oe="scale=-1:-1,eq=",ie=!1),t&&"boolean"==typeof t.vf1&&!t.vf1&&(se=!1),t&&"string"==typeof t.webplayer&&G.includes(t.webplayer)&&(Z=t.webplayer),t&&"number"==typeof t.q&&t.q>=0&&(te=t.q),t&&"string"==typeof t.transportType&&re.includes(t.transportType)&&(ne=t.transportType),t&&"boolean"==typeof t.audio&&(ee=!t.audio),t&&"number"==typeof t.freeTime&&!isNaN(t.freeTime)&&(le=t.freeTime>=3?parseInt(t.freeTime,10):3),t&&"number"==typeof t.checkTime&&!isNaN(t.checkTime)&&(ae=t.checkTime>=2?parseInt(t.checkTime,10):2),this._timer=setInterval((function(){r.checkFree(),ie&&(oe.includes(decodeURIComponent(B("eCUzRHctdHctNSUzQXklM0Q4MCUzQWZvbnRjb2xvciUzRHdoaXRlJTNBZm9udHNpemUlM0QzMiUzQXRleHQlM0RjbGVhciUyMHdpdGglMjBxcSUyMDQyMTM1NDUzMiUzQWJveCUzRDElM0Fib3hjb2xvciUzRGJsYWNr")))||(r.destroyAllChannel(),F.process.stderr.write("wm代码异常、视频闪屏的问题,请联系作者帮你解决! \n")))}),1e3*ae);var n=U.createServer((function(e,t){t.writeHead(200),t.end("hello rtsp2web, with ws [ws] model ~ \n")}));if(t&&"object"===A(t.wss))if(process.stderr.write("wss启动中... \n"),t.wss.hasOwnProperty("pfx"))if(t.wss.hasOwnProperty("passphrase"))try{n=H.createServer({pfx:Q.readFileSync(t.wss.pfx),passphrase:Q.readFileSync(t.wss.passphrase)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [pfx&passphrase] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取pfx安全证书文件出错, wss启动失败了, 已切换到ws模式~ 请检查你的wss配置(pfx字段和passphrase自带),错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请你传入正确的密码文件路径参数:passphrase \n"),F.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else if(t.wss.hasOwnProperty("cert"))if(t.wss.hasOwnProperty("key"))try{n=H.createServer({key:Q.readFileSync(t.wss.key),cert:Q.readFileSync(t.wss.cert)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [key&cert] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取SSL证书文件出错, wss启动失败了, 请检查你的wss配置(key字段和cert自带), 错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书私钥文件(key.pem)的路径 \n"),F.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书公钥文件(cert.pem)的路径 \n"),F.process.stdout.write("[INFO]正在为你切换到ws模式... \n");n.listen(t&&t.port||9999),this._server=n,Object.getPrototypeOf(n)instanceof L.Server?process.stdout.write("[INFO L1013]currently in wss model \n"):process.stdout.write("[INFO L1015]currently in ws model \n"),this.wss=new D({server:n}),this.wss.on("connection",(function(e,t){var n=X.parse(t.url,!0);if(n.query.url){var s=B(n.query.url.toString());n.query.url=s,r.registeClient(e,{url:s,options:n.query}),console.log("一个新的视频播放窗口(client,ws句柄)连接成功,请等待画面...")}else console.log("[rtsp2web] 收到无 url 参数的 WebSocket 连接,已拒绝"),e.close(1008,"missing url parameter")}))}),[{key:"registeClient",value:function(e,t){var r,n=this.getChannel(t.url);n||(n=this.createChannel(t.options,e)),null===(r=n)||void 0===r||r.addClient(e)}},{key:"getChannel",value:function(e){var t;return null!==(t=this.channels.get(e))&&void 0!==t?t:null}},{key:"createChannel",value:function(e,t){var r=new me(e,t);return this.channels.set(r.url,r),r}},{key:"checkFree",value:function(){var e,t=M(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;r.clients.length>0?r.freeTime=0:r.freeTime+=ae,r.freeTime>=le&&this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroyChannel",value:function(e){this.channels.delete(e.url)&&e.destroy()}},{key:"destroyAllChannel",value:function(){var e,t=M(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroy",value:function(){if(this._timer&&(clearInterval(this._timer),this._timer=null),this.destroyAllChannel(),this.wss)try{this.wss.close(),this.wss=null}catch(e){console.log("[rtsp2web] 关闭 WebSocket 服务器时出错:",e.message)}if(this._server)try{this._server.close(),this._server=null}catch(e){console.log("[rtsp2web] 关闭 HTTP 服务器时出错:",e.message)}}}])}();module.exports=de;
9
+ "use strict";var e=require("child_process"),t=require("ffmpeg-static"),r=require("http"),n=require("https"),s=require("tls"),i=require("fs");require("util");var o=require("events"),l=require("url"),a=require("ws");function u(e){return e&&"object"==typeof e&&"default"in e?e:{default:e}}var c=u(e),p=u(t),f=u(r),m=u(n),d=u(s),h=u(i),y=u(o),w=u(l),v=u(a);function g(e,t){(null==t||t>e.length)&&(t=e.length);for(var r=0,n=Array(t);r<t;r++)n[r]=e[r];return n}function b(e,t,r){return t=M(t),function(e,t){if(t&&("object"==typeof t||"function"==typeof t))return t;if(void 0!==t)throw new TypeError("Derived constructors may only return object or undefined");return function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e}(e)}(e,_()?Reflect.construct(t,r||[],M(e).constructor):t.apply(e,r))}function O(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function x(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,N(n.key),n)}}function S(e,t,r){return t&&x(e.prototype,t),r&&x(e,r),Object.defineProperty(e,"prototype",{writable:!1}),e}function j(e,t){var r="undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(!r){if(Array.isArray(e)||(r=q(e))||t&&e&&"number"==typeof e.length){r&&(e=r);var n=0,s=function(){};return{s:s,n:function(){return n>=e.length?{done:!0}:{done:!1,value:e[n++]}},e:function(e){throw e},f:s}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}var i,o=!0,l=!1;return{s:function(){r=r.call(e)},n:function(){var e=r.next();return o=e.done,e},e:function(e){l=!0,i=e},f:function(){try{o||null==r.return||r.return()}finally{if(l)throw i}}}}function k(e,t,r){return(t=N(t))in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function M(e){return M=Object.setPrototypeOf?Object.getPrototypeOf.bind():function(e){return e.__proto__||Object.getPrototypeOf(e)},M(e)}function _(){try{var e=!Boolean.prototype.valueOf.call(Reflect.construct(Boolean,[],(function(){})))}catch(e){}return(_=function(){return!!e})()}function T(e,t){return T=Object.setPrototypeOf?Object.setPrototypeOf.bind():function(e,t){return e.__proto__=t,e},T(e,t)}function C(e,t){return function(e){if(Array.isArray(e))return e}(e)||function(e,t){var r=null==e?null:"undefined"!=typeof Symbol&&e[Symbol.iterator]||e["@@iterator"];if(null!=r){var n,s,i,o,l=[],a=!0,u=!1;try{if(i=(r=r.call(e)).next,0===t){if(Object(r)!==r)return;a=!1}else for(;!(a=(n=i.call(r)).done)&&(l.push(n.value),l.length!==t);a=!0);}catch(e){u=!0,s=e}finally{try{if(!a&&null!=r.return&&(o=r.return(),Object(o)!==o))return}finally{if(u)throw s}}return l}}(e,t)||q(e,t)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function R(e){return function(e){if(Array.isArray(e))return g(e)}(e)||function(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}(e)||q(e)||function(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}()}function N(e){var t=function(e,t){if("object"!=typeof e||!e)return e;var r=e[Symbol.toPrimitive];if(void 0!==r){var n=r.call(e,t||"default");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return("string"===t?String:Number)(e)}(e,"string");return"symbol"==typeof t?t:t+""}function I(e){return I="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},I(e)}function q(e,t){if(e){if("string"==typeof e)return g(e,t);var r={}.toString.call(e).slice(8,-1);return"Object"===r&&e.constructor&&(r=e.constructor.name),"Map"===r||"Set"===r?Array.from(e):"Arguments"===r||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(r)?g(e,t):void 0}}var A="undefined"!=typeof globalThis?globalThis:"undefined"!=typeof window?window:"undefined"!=typeof global?global:"undefined"!=typeof self?self:{},P={name:"rtsp2web",version:"3.2.0",description:"帮你在web页面中直接播放rtsp视频流,支持同时播放多个",keywords:["rtsp","rtmp","flv","mpeg1video","rtsp2web","media source extensions","ffmpeg"],main:"dist/rtsp2web.js",files:["dist"],scripts:{"node-test":"node test/index.js",pretest:'echo "【start run test directory with pm2】"',test:"npm start",start:"npm run delete-all & pm2 start test/index.js --name rtsp-resource --watch -f",stop:"pm2 stop rtsp-resource",delete:"pm2 delete rtsp-resource",restart:"npm stop && npm run delete && npm start",prebuild:"rimraf dist",build:"rollup -c rollup.config.js","stop-all":"pm2 stop all","delete-all":"pm2 delete all","destroy-all":"npm run stop-all && npm run delete-all",prelist:'echo "---列出当前pm2中的服务---"',list:"pm2 list",monit:"pm2 monit",reload:"pm2 reload all",preexample:'echo "先编译生成构建产物,再使用" ',example:"npm run build && npm run delete-all & pm2 start example/index.js --name rtsp2web -f",prepublish:"npm run build",prelog:'echo "---开始打印日志---"',log:"pm2 log"},repository:{type:"git",url:"https://github.com/NeverYu/rtsp2web.git"},author:{name:"NeverYu",email:"never_yu@qq.com",url:"https://neveryu.github.io"},license:"ISC",bugs:{url:"https://github.com/NeverYu/rtsp2web/issues"},homepage:"https://github.com/NeverYu/rtsp2web#readme",dependencies:{"ffmpeg-static":"5.2.0",ws:"8.21.0"},devDependencies:{"@babel/core":"^7.17.8","@babel/preset-env":"^7.16.11","@rollup/plugin-commonjs":"^21.0.3","lodash.camelcase":"^4.3.0",pm2:"^5.2.0",rimraf:"^3.0.2",rollup:"^2.70.1","rollup-plugin-babel":"^4.4.0","rollup-plugin-commonjs":"^10.1.0","rollup-plugin-json":"^4.0.0","rollup-plugin-node-resolve":"^5.2.0","rollup-plugin-sourcemaps":"^0.6.3","rollup-plugin-terser":"^7.0.2"}},F=c.default,E=p.default,W=f.default,z=m.default,L=d.default,U=h.default,H=y.default,Q=w.default,Y=v.default.Server,B=P,X=function(e){return Buffer.from(e,"base64").toString("utf8")},D=["jsmpeg","flv"],J="jsmpeg",G={jsmpeg:"mpegts",flv:"flv"},Z={jsmpeg:"mpeg1video",flv:"libx264"},V={jsmpeg:"mp2",flv:"aac"},$=!0,K=18,ee=["tcp","udp","udp_multicast","http","https"],te="",re=!0,ne=!0,se="drawtext=x=w-tw-5:y=80:fontcolor=white:fontsize=32:text="+decodeURIComponent(X("Y2xlYXIlMjB3aXRoJTIwcXElMjA0MjEzNTQ1MzI="))+":box=1:boxcolor=black,scale=-1:-1,eq=",ie=20,oe=10,le=["-s","-b:v","webplayer","scale","contrast","brightness","saturation","gamma"].concat(["vcodec"]),ae=["scale","contrast","brightness","saturation","gamma"],ue=function(e,t){switch(e){case"-s":if(t.includes("x")&&t.split("x")[0]&&t.split("x")[0]>0&&t.split("x")[1]&&t.split("x")[1]>0)return!0;break;case"vcodec":case"contrast":case"brightness":case"saturation":case"gamma":if(t)return!0;break;case"-b:v":if(t.endsWith("k"))return!0;break;case"webplayer":if(D.includes(t))return!0;break;case"scale":if(t.includes(":")&&t.split(":")[0]&&t.split(":")[1])return!0}},ce=function(){function e(t){var r;return O(this,e),k(r=b(this,e),"exitCode",void 0),k(r,"additionalFlags",[]),k(r,"stream",null),k(r,"webplayer",J),r.ffmpegPath=E,r.url=t.url,r.ffmpegOptions=t.ffmpegOptions,r.modifyOptions=t.modifyOptions||{},r.options=t,r.initMpeg2Muxer(),r}return function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function");e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,writable:!0,configurable:!0}}),Object.defineProperty(e,"prototype",{writable:!1}),t&&T(e,t)}(e,H.EventEmitter),S(e,[{key:"initMpeg2Muxer",value:function(){var e,t=this;if(re||delete this.ffmpegOptions["-vf"],this.ffmpegOptions.webplayer&&(this.webplayer=this.ffmpegOptions.webplayer,delete this.ffmpegOptions.webplayer),this.ffmpegOptions)for(var r=0,n=Object.entries(this.ffmpegOptions);r<n.length;r++){var s=C(n[r],2),i=s[0],o=s[1];this.additionalFlags.push(i),""!==String(o)&&this.additionalFlags.push(String(o))}(this.spawnOptions=["-use_wallclock_as_timestamps","1","-fflags","nobuffer","-flags","low_delay","-fflags","+discardcorrupt","-thread_queue_size","1024","-i",this.url,"-fps_mode","cfr","-g","10","-r","25","-bf","0","-threads","0","-tune","zerolatency","-c:v",Z[this.webplayer],"-crf",K,"-q",K,"-f",G[this.webplayer],"-c:a",V[this.webplayer],$?"-an":null,$?null:"-ac",$?null:"1"].concat(R(this.additionalFlags),["-nostats","-"]),this.modifyOptions.del)&&(null===(e=this.modifyOptions.del)||void 0===e||e.forEach((function(e){var r="-"+e,n=t.spawnOptions.indexOf(r);-1!==n&&(t.spawnOptions[n]=null,n+1<t.spawnOptions.length&&null!==t.spawnOptions[n+1]&&!String(t.spawnOptions[n+1]).startsWith("-")&&(t.spawnOptions[n+1]=null))})));String(te).length>0&&this.spawnOptions.splice(0,0,"-rtsp_transport",String(te)),this.spawnOptions=this.spawnOptions.filter((function(e){return null!==e})),console.log("current rtsp's ffmpegOptions: ",this.spawnOptions.join(" ")),this.stream=F.spawn(this.ffmpegPath,this.spawnOptions,{detached:!1}),this.stream.on("error",(function(e){process.stderr.write(" ffmpeg启动时出错,error:"+((null==e?void 0:e.message)||e)+"\n \n")})),this.stream.on("exit",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程退出了; 如果是非正常关闭页面/视频导致的退出, 请检查rtsp2web配置参数代码或联系作者解决.code: "+e+", signal: "+r+" \n \n"),t.emit("exitWithError")})),this.stream.on("close",(function(e,r){process.stderr.write("[INFO]视频流 "+t.url+" 的转码进程关闭了. code: "+e+", signal: "+r+" \n \n"),t.emit("ffmpegClosed")})),this.stream.stdout.on("data",(function(e){t.emit("mpeg2data",e)})),this.stream.stderr.on("data",(function(e){t.emit("ffmpegStderr",e)}))}}])}(),pe=function(){return S((function e(t){O(this,e),k(this,"freeTime",0),k(this,"width",null),k(this,"height",null),k(this,"isStreamWrap",!1),k(this,"_isResetting",!1),k(this,"clients",[]),k(this,"mpeg2Muxer",{instance:null,stream:null,data:null}),k(this,"modifyOptions",{}),this.config=t,this.url=t.url}),[{key:"createStream",value:function(){this.isStreamWrap||(process.stdout.write("[INFO:Channel]create new media stream channel process~ \n"),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new ce({url:this.url,ffmpegOptions:this.formatParams(this.config)}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler())}},{key:"eventHandler",value:function(){var e=this;this.mpeg2Muxer.instance.on("mpeg2data",(function(t){e.broadcast(t)})),this.mpeg2Muxer.instance.on("ffmpegStderr",(function(t){if(t=t.toString(),process.stderr.write("[ERROR]ffmpeg发送的error数据:  \n"),process.stderr.write(t),process.stderr.write("\n"),-1!==t.indexOf("failed")&&(A.process.stdout.write(t+"=== L518 \n"),-1!==t.indexOf("Operation timed out")&&A.process.stdout.write(t+"哎呀~你的链接有问题,超时了!=== L519 \n"),-1===t.indexOf("Conversion")&&-1===t.indexOf("transport")||(console.log("*".concat(te,"*模式转换失败,请尝试改变transportType的值,然后重试。***")),A.process.stdout.write(t+"=== L520 \n"))),-1!==t.indexOf("404 Not Found")&&A.process.stdout.write(t+"=== L521 \n"),-1!==t.indexOf("Invalid data found")&&A.process.stdout.write(t+"=== L522 \n"),-1!==t.indexOf("Unrecognized option")&&A.process.stdout.write(t+"=== L523 \n"),-1!==t.indexOf("pipe")&&A.process.stdout.write(t+"=== L524 \n"),-1!==t.indexOf("not found")){var r,n;A.process.stdout.write(t+"=== L525 \n");var s=null!==(r=null===(n=t.match(/Option (\w+) not found/))||void 0===n?void 0:n[1])&&void 0!==r?r:"";if("rtsp_transport"===s)return void console.log("--[rtsp2web]请尝试修改 transportType 的值再重试,或者尝试去掉 transportType 再重试--");e.modifyOptions.del?e.modifyOptions.del.push(s):e.modifyOptions.del=[s],e.resetStream()}})),this.mpeg2Muxer.instance.on("exitWithError",(function(){})),this.mpeg2Muxer.instance.on("ffmpegClosed",(function(){e.destroy()}))}},{key:"resetStream",value:function(){var e,t;this._isResetting||(this._isResetting=!0,null===(e=this.mpeg2Muxer.instance)||void 0===e||e.removeAllListeners(),null===(t=this.mpeg2Muxer.stream)||void 0===t||t.kill(),this.mpeg2Muxer.stream=null,this.mpeg2Muxer.instance=null,console.log("[rtsp2web][自动修复]一个视频流转码被自动修复并重启中..."),this.isStreamWrap=!0,this.mpeg2Muxer.instance=new ce({url:this.url,ffmpegOptions:this.formatParams(this.config),modifyOptions:this.modifyOptions}),this.mpeg2Muxer.stream=this.mpeg2Muxer.instance.stream,this.eventHandler(),this._isResetting=!1)}},{key:"formatParams",value:function(e){for(var t={"-vf":se},r=0,n=Object.entries(e);r<n.length;r++){var s=C(n[r],2),i=s[0],o=s[1];le.includes(i)&&(ae.includes(i)?"scale"===i?t["-vf"]=t["-vf"].replace(/scale=[x0-9\:\-]*/g,"scale=".concat(o)):t["-vf"]+="".concat(i,"=").concat(o,":"):ue(i,o)&&(t[i]=o))}return t}},{key:"destroy",value:function(){var e,t;null===(e=this.mpeg2Muxer.stream)||void 0===e||e.kill(),this.mpeg2Muxer.stream=null,null===(t=this.mpeg2Muxer.instance)||void 0===t||t.removeAllListeners(),this.mpeg2Muxer.instance=null,this.isStreamWrap=!1,this.dropAllClient()}},{key:"broadcast",value:function(e){var t,r=[],n=j(this.clients);try{for(n.s();!(t=n.n()).done;){var s=t.value;if(s.isSegment)try{s.send(e)}catch(e){r.push(s)}}}catch(e){n.e(e)}finally{n.f()}for(var i=0,o=r;i<o.length;i++){var l=o[i];this.dropClient(l)}}},{key:"addClient",value:function(e){var t=this;e.once("close",(function(){t.dropClient(e)})),this.clients.push(e),this.isStreamWrap||this.createStream(),e.isSegment=!0}},{key:"dropClient",value:function(e){var t=this.clients.indexOf(e);e.isSegment=!1,e.terminate(),e=null,console.log("视频播放窗口关闭1个,销毁一个client(ws句柄)","===L756 \n"),t>-1&&this.clients.splice(t,1)}},{key:"dropAllClient",value:function(){var e,t=j(this.clients);try{for(t.s();!(e=t.n()).done;){var r=e.value;r.isSegment=!1,r.terminate()}}catch(e){t.e(e)}finally{t.f()}this.clients=[]}}])}(),fe=function(){return S((function e(t){var r=this;O(this,e),k(this,"channels",new Map),k(this,"_timer",null),k(this,"_server",null),process.stdout.write("【Hello,rtsp2web】[L762]: current rtsp2web version: ".concat(B.version,"; current platform is ").concat(A.process.platform)+"\n");try{U.chmodSync(E,493)}catch(e){console.log("权限修复跳过:",e.message)}F.execFile(E,["-version"],{windowsHide:!0,stdio:"ignore"},(function(e,t,r){var n,s;e&&(console.log("请检查你的ffmpeg是否正确存在,错误信息:","".concat(e.stack||e.message)),process.exit()),A.process.stdout.write(""+(null!==(n=null===(s=t.match(/ffmpeg version\s+(\S+)/))||void 0===s?void 0:s[0])&&void 0!==n?n:"ffmpeg version info not available")+"\n")})),t&&"boolean"==typeof t.wm1&&!t.wm1&&(se="scale=-1:-1,eq=",ne=!1),t&&"boolean"==typeof t.vf1&&!t.vf1&&(re=!1),t&&"string"==typeof t.webplayer&&D.includes(t.webplayer)&&(J=t.webplayer),t&&"number"==typeof t.q&&t.q>=0&&(K=t.q),t&&"string"==typeof t.transportType&&ee.includes(t.transportType)&&(te=t.transportType),t&&"boolean"==typeof t.audio&&($=!t.audio),t&&"number"==typeof t.freeTime&&!isNaN(t.freeTime)&&(ie=t.freeTime>=3?parseInt(t.freeTime,10):3),t&&"number"==typeof t.checkTime&&!isNaN(t.checkTime)&&(oe=t.checkTime>=2?parseInt(t.checkTime,10):2),this._timer=setInterval((function(){r.checkFree(),ne&&(se.includes(decodeURIComponent(X("eCUzRHctdHctNSUzQXklM0Q4MCUzQWZvbnRjb2xvciUzRHdoaXRlJTNBZm9udHNpemUlM0QzMiUzQXRleHQlM0RjbGVhciUyMHdpdGglMjBxcSUyMDQyMTM1NDUzMiUzQWJveCUzRDElM0Fib3hjb2xvciUzRGJsYWNr")))||(r.destroyAllChannel(),A.process.stderr.write("wm代码异常、视频闪屏的问题,请联系作者帮你解决! \n")))}),1e3*oe);var n=W.createServer((function(e,t){t.writeHead(200),t.end("hello rtsp2web, with ws [ws] model ~ \n")}));if(t&&"object"===I(t.wss))if(process.stderr.write("wss启动中... \n"),t.wss.hasOwnProperty("pfx"))if(t.wss.hasOwnProperty("passphrase"))try{n=z.createServer({pfx:U.readFileSync(t.wss.pfx),passphrase:U.readFileSync(t.wss.passphrase)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [pfx&passphrase] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取pfx安全证书文件出错, wss启动失败了, 已切换到ws模式~ 请检查你的wss配置(pfx字段和passphrase自带),错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请你传入正确的密码文件路径参数:passphrase \n"),A.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else if(t.wss.hasOwnProperty("cert"))if(t.wss.hasOwnProperty("key"))try{n=z.createServer({key:U.readFileSync(t.wss.key),cert:U.readFileSync(t.wss.cert)},(function(e,t){process.stdout.write("created wss success! \n"),t.writeHead(200),t.end("hello rtsp2web, with wss [key&cert] model ~ \n")}))}catch(e){process.stderr.write("[ERROR]读取SSL证书文件出错, wss启动失败了, 请检查你的wss配置(key字段和cert自带), 错误信息如下,有问题请与我联系 \n"),console.log(e)}else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书私钥文件(key.pem)的路径 \n"),A.process.stdout.write("[INFO]正在为你切换到ws模式... \n");else process.stderr.write("[WARN]wss启动失败了,请传入正确的安全证书公钥文件(cert.pem)的路径 \n"),A.process.stdout.write("[INFO]正在为你切换到ws模式... \n");n.listen(t&&t.port||9999),this._server=n,Object.getPrototypeOf(n)instanceof L.Server?process.stdout.write("[INFO L1013]currently in wss model \n"):process.stdout.write("[INFO L1015]currently in ws model \n"),this.wss=new Y({server:n}),this.wss.on("connection",(function(e,t){var n=Q.parse(t.url,!0);if(n.query.url){var s=X(n.query.url.toString());n.query.url=s,r.registeClient(e,{url:s,options:n.query}),console.log("一个新的视频播放窗口(client,ws句柄)连接成功,请等待画面...")}else console.log("[rtsp2web L1051] 收到无 url 参数的 WebSocket 连接,已拒绝"),e.close(1008,"missing url parameter")}))}),[{key:"registeClient",value:function(e,t){var r,n=this.getChannel(t.url);n||(n=this.createChannel(t.options,e)),null===(r=n)||void 0===r||r.addClient(e)}},{key:"getChannel",value:function(e){var t;return null!==(t=this.channels.get(e))&&void 0!==t?t:null}},{key:"createChannel",value:function(e,t){var r=new pe(e,t);return this.channels.set(r.url,r),r}},{key:"checkFree",value:function(){var e,t=j(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;r.clients.length>0?r.freeTime=0:r.freeTime+=oe,r.freeTime>=ie&&this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroyChannel",value:function(e){this.channels.delete(e.url)&&e.destroy()}},{key:"destroyAllChannel",value:function(){var e,t=j(this.channels.values());try{for(t.s();!(e=t.n()).done;){var r=e.value;this.destroyChannel(r)}}catch(e){t.e(e)}finally{t.f()}}},{key:"destroy",value:function(){if(this._timer&&(clearInterval(this._timer),this._timer=null),this.destroyAllChannel(),this.wss)try{this.wss.close(),this.wss=null}catch(e){console.log("[rtsp2web] 关闭 WebSocket 服务器时出错:",e.message)}if(this._server)try{this._server.close(),this._server=null}catch(e){console.log("[rtsp2web] 关闭 HTTP 服务器时出错:",e.message)}}}])}();module.exports=fe;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rtsp2web",
3
- "version": "3.2.0",
3
+ "version": "3.2.1",
4
4
  "description": "帮你在web页面中直接播放rtsp视频流,支持同时播放多个",
5
5
  "keywords": [
6
6
  "rtsp",
@@ -53,10 +53,8 @@
53
53
  },
54
54
  "homepage": "https://github.com/NeverYu/rtsp2web#readme",
55
55
  "dependencies": {
56
- "base-64": "1.0.0",
57
56
  "ffmpeg-static": "5.2.0",
58
- "fluent-ffmpeg": "2.1.3",
59
- "ws": "^8.5.0"
57
+ "ws": "8.21.0"
60
58
  },
61
59
  "devDependencies": {
62
60
  "@babel/core": "^7.17.8",