@ezuikit/utils-tools 2.0.7 → 2.0.9

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/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
- * @ezuikit/utils-tools v2.0.7
2
+ * @ezuikit/utils-tools v2.0.9
3
3
  * tools utils
4
- * Copyright (c) 2026-09-02 Ezviz-OpenBiz
4
+ * Copyright (c) 2026-11-03 Ezviz-OpenBiz
5
5
  * Released under the MIT License.
6
6
  */
7
- "use strict";function isHttp(url){return/^http[s]?:\/\//.test(url)}var getQuery=function(url){var query=url.split("?")[1],obj={};if(query)for(var vars=query.split("&"),i=0;i<vars.length;i++){var pair=vars[i].split("=");obj[pair[0]]=decodeURIComponent(pair[1])}return obj};function parseEzopenUrl(url){var obj={};if(/^ezopen:\/\//.test(url)){if(url.includes("@")){var endIndex=url.indexOf("@"),startIndex=url.indexOf("//");obj.validateCode=url.substring(startIndex+2,endIndex),url=url.replace(obj.validateCode+"@","")}obj.protocol=url.split("//")[0],obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url;var pathnames=obj.pathname.split("/"),lastPath=pathnames[2].split(".");return obj.deviceSerial=pathnames[1],obj.channelNo=lastPath[0],obj.streamTypeIn=pathnames[2].includes(".hd.")?1:2,obj.type=lastPath[lastPath.length-1],"live"===obj.type&&(obj.definition=lastPath.length>2?lastPath[1]:"sd"),"rec"===obj.type&&pathnames[2]&&(obj.recType=pathnames[2].includes(".cloud.")?"cloud":""),obj.searchParams=getQuery(url),obj}if(isHttp(url))try{var u=new URL(url),file=u.pathname.split("/").pop();if(file&&["live","playback","cloudplayback","download"].includes(file)&&u.search.includes("dev=")&&u.search.includes("stream=")){var deviceSerial=u.searchParams.get("dev"),channelNo=u.searchParams.get("chn")||"1",sessionToken=u.searchParams.get("ssn"),stream=u.searchParams.get("stream"),streamTypeIn=Number(stream);if("https:"!==u.protocol||!deviceSerial||!channelNo||!sessionToken)return{};var searchParams={};u.searchParams.forEach((function(value,key){searchParams[key]=value})),obj.protocol=u.protocol,obj.search=u.search,obj.searchParams=searchParams,obj.pathname=u.pathname,obj.origin=u.origin,obj.href=url,obj.hostname=u.host,obj.deviceSerial=deviceSerial,obj.channelNo=channelNo,obj.streamTypeIn=streamTypeIn;var validateCode=u.searchParams.get("code");return validateCode&&(obj.validateCode=validateCode),"live"===file?(obj.type="live",obj.definition=1===streamTypeIn?"hd":"sd"):"playback"===file?(obj.type="rec",obj.recType=""):"cloudplayback"===file?(obj.type="rec",obj.recType="cloud"):obj.type="download",obj}if(file){var m=file.match(/^([^_]+)_(\d+)_(\d+)\./);if(m){var deviceSerial1=m[1],channelNo1=m[2],quality=m[3];return obj.deviceSerial=deviceSerial1,obj.channelNo=channelNo1,obj.streamTypeIn=+quality,u.searchParams.get("code")&&(obj.validateCode=u.searchParams.get("code")),obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.protocol=url.split("//")[0],obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url,obj.type="live",(url.includes("rec=local")||url.includes("rec=cloud"))&&(obj.type="rec",url.includes("rec=cloud")?obj.recType="cloud":obj.recType=""),"live"===obj.type&&(obj.definition="1"===quality?"hd":"sd"),obj.searchParams=getQuery(url),obj}}}catch(e){}return{}}var codec={h264:1,h265:2,h266:4,vp8:8,vp9:16,av1:32},getQueryVC=function(CODECS){return CODECS.reduce((function(acc,key){return key=key.toLowerCase(),acc+(codec[key]||0)}),0)};function _array_like_to_array(arr,len){(null==len||len>arr.length)&&(len=arr.length);for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _instanceof(left,right){return null!=right&&"undefined"!=typeof Symbol&&right[Symbol.hasInstance]?!!right[Symbol.hasInstance](left):left instanceof right}function _create_for_of_iterator_helper_loose(o,allowArrayLike){var it="undefined"!=typeof Symbol&&o[Symbol.iterator]||o["@@iterator"];if(it)return(it=it.call(o)).next.bind(it);if(Array.isArray(o)||(it=function(o,minLen){if(o){if("string"==typeof o)return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);return"Object"===n&&o.constructor&&(n=o.constructor.name),"Map"===n||"Set"===n?Array.from(n):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_array_like_to_array(o,minLen):void 0}}(o))||allowArrayLike){it&&(o=it);var i=0;return function(){return i>=o.length?{done:!0}:{done:!1,value:o[i++]}}}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 DateTime=function(){function DateTime(){}return DateTime.normalizeUnit=function(unit){return"year"===unit||"y"===unit||"年"===unit?"year":"month"===unit||"M"===unit||"月"===unit?"month":"day"===unit||"d"===unit||"日"===unit?"day":"hour"===unit||"h"===unit||"时"===unit?"hour":"minute"===unit||"m"===unit||"分"===unit?"minute":"second"},DateTime.daysInMonth=function(year,month){return new Date(year,month+1,0).getDate()},DateTime.shiftMonth=function(baseDate,months){var result=new Date(baseDate.getTime()),currentDate=result.getDate();result.setDate(1),result.setMonth(result.getMonth()+months);var maxDate=DateTime.daysInMonth(result.getFullYear(),result.getMonth());return result.setDate(Math.min(currentDate,maxDate)),result},DateTime.add=function(input,value,unit){if(void 0===unit&&(unit="day"),!Number.isFinite(value))throw new Error("Invalid value");var baseDate=DateTime.toDate(input),normalizedUnit=DateTime.normalizeUnit(unit);if("year"===normalizedUnit)return DateTime.shiftMonth(baseDate,12*value);if("month"===normalizedUnit)return DateTime.shiftMonth(baseDate,value);var result=new Date(baseDate.getTime());return result.setTime(result.getTime()+value*{day:864e5,hour:36e5,minute:6e4,second:1e3}[normalizedUnit]),result},DateTime.subtract=function(input,value,unit){return void 0===unit&&(unit="day"),DateTime.add(input,-value,unit)},DateTime.fillZero=function(num,len){return void 0===len&&(len=2),num.toString().padStart(len,"0")},DateTime.format=function(input,format){var date;if(_instanceof(input,Date))date=input;else{if("number"!=typeof input&&"string"!=typeof input)throw new Error("Invalid date input");date=DateTime.toDate(input+"")}for(var _step,result=format,_iterator=_create_for_of_iterator_helper_loose([[/(yyyy|YYYY)/g,function(){return DateTime.fillZero(date.getFullYear(),4)}],[/(yy|YY)/g,function(){return DateTime.fillZero(date.getFullYear()%100,2)}],[/(MM)/g,function(){return DateTime.fillZero(date.getMonth()+1,2)}],[/(M)/g,function(){return(date.getMonth()+1).toString()}],[/(dd|DD)/g,function(){return DateTime.fillZero(date.getDate(),2)}],[/(d|D)/g,function(){return date.getDate().toString()}],[/(HH|hh)/g,function(){return DateTime.fillZero(date.getHours(),2)}],[/(H|h)/g,function(){return date.getHours().toString()}],[/(mm)/g,function(){return DateTime.fillZero(date.getMinutes(),2)}],[/(m)/g,function(){return date.getMinutes().toString()}],[/(ss|SS)/g,function(){return DateTime.fillZero(date.getSeconds(),2)}],[/(s|S)/g,function(){return date.getSeconds().toString()}],[/(fff)/g,function(){return DateTime.fillZero(date.getMilliseconds(),3)}]]);!(_step=_iterator()).done;){var _step_value=_step.value,regexp=_step_value[0],fn=_step_value[1];result=result.replace(regexp,fn)}return result},DateTime.toDate=function(str){if(_instanceof(str,Date))return str;str=(str+"").trim().replace(/\/|\./gi,"-"),/^\d{4}$/.test(str)&&(str+="-01"),/^\d{4}-\d{2}$/.test(str)&&(str+="-01");try{return/^\d{4}-\d{2}-\d{2}$/.test(str)?new Date(+str.slice(0,4),+str.slice(5,7)-1,+str.slice(8,10),0,0,0):/^\d{8}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),0,0,0)):/^\d{14}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),+str.slice(8,10),+str.slice(10,12),+str.slice(12,14))):/^\d{13}$/.test(str)?new Date(Number(str)):/^\d{10}$/.test(str)?new Date(1e3*Number(str)):new Date(str)}catch(error){throw new Error("Invalid date string")}},DateTime.diff=function(date1,date2,type){void 0===type&&(type="second");var d1=DateTime.toDate(date1),d2=DateTime.toDate(date2);return"second"===type?Math.floor((d1.getTime()-d2.getTime())/1e3):"minute"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60):"hour"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60):"day"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60/24):Math.abs(d1.getTime()-d2.getTime())},DateTime}();exports.DateTime=DateTime,exports.addVc=function(url,codecs){void 0===codecs&&(codecs=["h264"]);var vc=getQueryVC(codecs||["h264"]),host=url.split("?")[0],query=url.split("?")[1];return query=(query||"").split("&").filter((function(item){return!/^vc=\d?/.test(item)})).join("&"),host+"?"+(query+=(query?"&":"")+"vc="+vc)},exports.getQuery=getQuery,exports.getQueryVC=getQueryVC,exports.getStaticPath=function(path,base){void 0===base&&(base="");var protocolReg=/^(https?:\/\/|^\/\/)/;if(""===path||void 0===path)return"";if(protocolReg.test(path))return path;path=path.replace(/\/+/g,"/"),base=protocolReg.test(base||"")?base:window.location.href;try{return new URL(path,base).href}catch(error){return path}},exports.isEmpty=function(param){return void 0===param||""===param||null===param},exports.isHttp=isHttp,exports.isMobile=function(agent){var _navigator,_navigator1,_navigator2,_window,_navigator_maxTouchPoints;return/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|Opera Mini)/i.test(null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)||/Macintosh/i.test(agent||(null==(_navigator1=navigator)?void 0:_navigator1.userAgent))&&(null!=(_navigator_maxTouchPoints=null==(_navigator2=navigator)?void 0:_navigator2.maxTouchPoints)?_navigator_maxTouchPoints:0)>1||!!(null==(_window=window)?void 0:_window.__IS_MOBILE_SIMULATOR__)},exports.isRealMobile=function(agent){var _navigator,_ref,ua=(null!=(_ref=null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)?_ref:"").toLowerCase();if(/ipad|tablet|playbook|silk|android(?!.*mobile)/i.test(ua))return!1;var hasTouch="ontouchstart"in window||navigator.maxTouchPoints>0;return/android|webos|iphone|ipod|blackberry|iemobile|opera mini/i.test(ua)&&hasTouch},exports.objectIsNull=function(obj){try{return"{}"===JSON.stringify(obj)}catch(error){return!1}},exports.parseEzopenUrl=parseEzopenUrl,exports.pick=function(obj,keys){return Object.entries(obj).reduce((function(acc,param){var key=param[0],value=param[1];return keys.includes(key)&&(acc[key]=value),acc}),{})},exports.switchEzopenUrl=function(url,options){var _ref=null!=options?options:{},type=_ref.type,recType=_ref.recType,search=_ref.search,definition=_ref.definition,channelNo=_ref.channelNo,deviceSerial=_ref.deviceSerial,validateCode=_ref.validateCode,obj=parseEzopenUrl(url);if(search){var ns=Object.assign({},obj.searchParams,getQuery("?"+search.replace("?","")));search=Object.entries(ns).reduce((function(acc,param){var key=param[0],value=param[1];return""===value?acc:acc+=key+"="+encodeURIComponent(value)+"&"}),"?").replace(/&$/,"")}else search=obj.search;return type=type||obj.type,recType=null!=recType?recType:obj.recType,definition=null!=definition?definition:obj.definition,channelNo=channelNo||obj.channelNo,deviceSerial=deviceSerial||obj.deviceSerial,validateCode=null!=validateCode?validateCode:obj.validateCode,obj.protocol+"//"+(validateCode?validateCode+"@":"")+obj.hostname+"/"+deviceSerial+"/"+channelNo+("rec"===type&&recType?"."+recType:"")+("live"===type&&"hd"===definition?"."+definition:"")+"."+type+search};
7
+ "use strict";function isHttp(url){return/^http[s]?:\/\//.test(url)}var getQuery=function(url){var query=url.split("?")[1],obj={};if(query)for(var vars=query.split("&"),i=0;i<vars.length;i++){var pair=vars[i].split("=");obj[pair[0]]=decodeURIComponent(pair[1])}return obj};function parseEzopenUrl(url){var obj={};if(/^ezopen:\/\//.test(url)){if(url.includes("@")){var endIndex=url.indexOf("@"),startIndex=url.indexOf("//");obj.validateCode=url.substring(startIndex+2,endIndex),url=url.replace(obj.validateCode+"@","")}obj.protocol=url.split("//")[0],obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url;var pathnames=obj.pathname.split("/"),lastPath=pathnames[2].split(".");return obj.deviceSerial=pathnames[1],obj.channelNo=lastPath[0],obj.streamTypeIn=pathnames[2].includes(".hd.")?1:2,obj.type=lastPath[lastPath.length-1],"live"===obj.type&&(obj.definition=lastPath.length>2?lastPath[1]:"sd"),"rec"===obj.type&&pathnames[2]&&(obj.recType=pathnames[2].includes(".cloud.")?"cloud":""),obj.searchParams=getQuery(url),obj}if(isHttp(url))try{var u=new URL(url),file=u.pathname.split("/").pop();if(file&&["live","playback","cloudplayback","download"].includes(file)&&u.search.includes("dev=")&&u.search.includes("stream=")){var deviceSerial=u.searchParams.get("dev"),channelNo=u.searchParams.get("chn")||"1",sessionToken=u.searchParams.get("ssn"),stream=u.searchParams.get("stream"),streamTypeIn=Number(stream);if(!("https:"===u.protocol&&deviceSerial&&channelNo&&sessionToken&&streamTypeIn))return{};var searchParams={};u.searchParams.forEach(function(value,key){searchParams[key]=value}),obj.protocol=u.protocol,obj.search=u.search,obj.searchParams=searchParams,obj.pathname=u.pathname,obj.origin=u.origin,obj.href=url,obj.hostname=u.host,obj.deviceSerial=deviceSerial,obj.channelNo=channelNo,obj.streamTypeIn=streamTypeIn;var validateCode=u.searchParams.get("code");return validateCode&&(obj.validateCode=validateCode),"live"===file?(obj.type="live",obj.definition=1===streamTypeIn?"hd":"sd"):"playback"===file?(obj.type="rec",obj.recType=""):"cloudplayback"===file?(obj.type="rec",obj.recType="cloud"):obj.type="download",obj}if(file){var m=file.match(/^([^_]+)_(\d+)_(\d+)\./);if(m){var deviceSerial1=m[1],channelNo1=m[2],quality=m[3];return obj.deviceSerial=deviceSerial1,obj.channelNo=channelNo1,obj.streamTypeIn=+quality,u.searchParams.get("code")&&(obj.validateCode=u.searchParams.get("code")),obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.protocol=url.split("//")[0],obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url,obj.type="live",(url.includes("rec=local")||url.includes("rec=cloud"))&&(obj.type="rec",url.includes("rec=cloud")?obj.recType="cloud":obj.recType=""),"live"===obj.type&&(obj.definition="1"===quality?"hd":"sd"),obj.searchParams=getQuery(url),obj}}}catch(e){}return{}}function isEzvizUrl(url){var _url_split,path=url.split("?")[0],queryStr=(null==(_url_split=url.split("?"))?void 0:_url_split[1])||"";if(/^http[s]?:\/\//.test(path)&&/\/openlive\/|\/openpb\//.test(path)&&(/\.flv$/i.test(path)||/\.m3u8$/i.test(path)||/_\d+$/.test(path))){var newPath=path.replace(/\.flv|\.m3u8/gi,"");if(/_\d+_\d+$/.test(newPath))return!0}return/^ezopen:\/\//.test(path)||/\/(playback|cloudplayback|live)$/.test(path)&&queryStr&&/stream=\d+/.test(queryStr)&&queryStr.includes("dev=")&&queryStr.includes("ssn=")}var codec={h264:1,h265:2,h266:4,vp8:8,vp9:16,av1:32},getQueryVC=function(CODECS){return CODECS.reduce(function(acc,key){return key=key.toLowerCase(),acc+(codec[key]||0)},0)};function _array_like_to_array(arr,len){(null==len||len>arr.length)&&(len=arr.length);for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _create_for_of_iterator_helper_loose(o,allowArrayLike){var it="undefined"!=typeof Symbol&&o[Symbol.iterator]||o["@@iterator"];if(it)return(it=it.call(o)).next.bind(it);if(Array.isArray(o)||(it=function(o,minLen){if(!o)return;if("string"==typeof o)return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);"Object"===n&&o.constructor&&(n=o.constructor.name);if("Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _array_like_to_array(o,minLen)}(o))||allowArrayLike){it&&(o=it);var i=0;return function(){return i>=o.length?{done:!0}:{done:!1,value:o[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _instanceof(left,right){return null!=right&&"undefined"!=typeof Symbol&&right[Symbol.hasInstance]?!!right[Symbol.hasInstance](left):left instanceof right}var DateTime=function(){function DateTime(){}return DateTime.normalizeUnit=function(unit){return"year"===unit||"y"===unit||"年"===unit?"year":"month"===unit||"M"===unit||"月"===unit?"month":"day"===unit||"d"===unit||"日"===unit?"day":"hour"===unit||"h"===unit||"时"===unit?"hour":"minute"===unit||"m"===unit||"分"===unit?"minute":"second"},DateTime.daysInMonth=function(year,month){return new Date(year,month+1,0).getDate()},DateTime.shiftMonth=function(baseDate,months){var result=new Date(baseDate.getTime()),currentDate=result.getDate();result.setDate(1),result.setMonth(result.getMonth()+months);var maxDate=DateTime.daysInMonth(result.getFullYear(),result.getMonth());return result.setDate(Math.min(currentDate,maxDate)),result},DateTime.add=function(input,value,unit){if(void 0===unit&&(unit="day"),!Number.isFinite(value))throw new Error("Invalid value");var baseDate=DateTime.toDate(input),normalizedUnit=DateTime.normalizeUnit(unit);if("year"===normalizedUnit)return DateTime.shiftMonth(baseDate,12*value);if("month"===normalizedUnit)return DateTime.shiftMonth(baseDate,value);var result=new Date(baseDate.getTime());return result.setTime(result.getTime()+value*{day:864e5,hour:36e5,minute:6e4,second:1e3}[normalizedUnit]),result},DateTime.subtract=function(input,value,unit){return void 0===unit&&(unit="day"),DateTime.add(input,-value,unit)},DateTime.fillZero=function(num,len){return void 0===len&&(len=2),num.toString().padStart(len,"0")},DateTime.format=function(input,format){var date;if(_instanceof(input,Date))date=input;else{if("number"!=typeof input&&"string"!=typeof input)throw new Error("Invalid date input");date=DateTime.toDate(input+"")}for(var _step,result=format,_iterator=_create_for_of_iterator_helper_loose([[/(yyyy|YYYY)/g,function(){return DateTime.fillZero(date.getFullYear(),4)}],[/(yy|YY)/g,function(){return DateTime.fillZero(date.getFullYear()%100,2)}],[/(MM)/g,function(){return DateTime.fillZero(date.getMonth()+1,2)}],[/(M)/g,function(){return(date.getMonth()+1).toString()}],[/(dd|DD)/g,function(){return DateTime.fillZero(date.getDate(),2)}],[/(d|D)/g,function(){return date.getDate().toString()}],[/(HH|hh)/g,function(){return DateTime.fillZero(date.getHours(),2)}],[/(H|h)/g,function(){return date.getHours().toString()}],[/(mm)/g,function(){return DateTime.fillZero(date.getMinutes(),2)}],[/(m)/g,function(){return date.getMinutes().toString()}],[/(ss|SS)/g,function(){return DateTime.fillZero(date.getSeconds(),2)}],[/(s|S)/g,function(){return date.getSeconds().toString()}],[/(fff)/g,function(){return DateTime.fillZero(date.getMilliseconds(),3)}]]);!(_step=_iterator()).done;){var _step_value=_step.value,regexp=_step_value[0],fn=_step_value[1];result=result.replace(regexp,fn)}return result},DateTime.toDate=function(str){if(_instanceof(str,Date))return str;str=(str+"").trim().replace(/\/|\./gi,"-"),/^\d{4}$/.test(str)&&(str+="-01"),/^\d{4}-\d{2}$/.test(str)&&(str+="-01");try{return/^\d{4}-\d{2}-\d{2}$/.test(str)?new Date(+str.slice(0,4),+str.slice(5,7)-1,+str.slice(8,10),0,0,0):/^\d{8}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),0,0,0)):/^\d{14}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),+str.slice(8,10),+str.slice(10,12),+str.slice(12,14))):/^\d{13}$/.test(str)?new Date(Number(str)):/^\d{10}$/.test(str)?new Date(1e3*Number(str)):new Date(str)}catch(error){throw new Error("Invalid date string")}},DateTime.diff=function(date1,date2,type){void 0===type&&(type="second");var d1=DateTime.toDate(date1),d2=DateTime.toDate(date2);return"second"===type?Math.floor((d1.getTime()-d2.getTime())/1e3):"minute"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60):"hour"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60):"day"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60/24):Math.abs(d1.getTime()-d2.getTime())},DateTime}();function getNavigatorLike(){if("undefined"!=typeof navigator)return navigator}function getWindowLike(){if("undefined"!=typeof window)return window}function detectSecureContext(){var win=getWindowLike();if("boolean"==typeof(null==win?void 0:win.isSecureContext))return win.isSecureContext;if("undefined"==typeof location)return!1;if("https:"===location.protocol||"file:"===location.protocol)return!0;var hostname=location.hostname||"";return"localhost"===hostname||/\.localhost$/.test(hostname)||"127.0.0.1"===hostname||"[::1]"===hostname||"::1"===hostname}function withTimeout(promise,timeout){return timeout>0?new Promise(function(resolve,reject){var settled=!1,timer=setTimeout(function(){settled||(settled=!0,reject(new Error("[microphone] detect timeout")))},timeout),finish=function(run){settled||(settled=!0,clearTimeout(timer),run())};promise.then(function(value){return finish(function(){return resolve(value)})},function(error){return finish(function(){return reject(error)})})}):promise}function getMicrophoneCapabilities(){var _nav_permissions,nav=getNavigatorLike(),win=getWindowLike(),mediaDevices=null==nav?void 0:nav.mediaDevices;return{secureContext:detectSecureContext(),mediaDevices:!!mediaDevices,getUserMedia:"function"==typeof(null==mediaDevices?void 0:mediaDevices.getUserMedia),legacyGetUserMedia:"function"==typeof(null==nav?void 0:nav.getUserMedia)||"function"==typeof(null==nav?void 0:nav.webkitGetUserMedia)||"function"==typeof(null==nav?void 0:nav.mozGetUserMedia)||"function"==typeof(null==nav?void 0:nav.msGetUserMedia),enumerateDevices:"function"==typeof(null==mediaDevices?void 0:mediaDevices.enumerateDevices),permissionsQuery:"function"==typeof(null==nav||null==(_nav_permissions=nav.permissions)?void 0:_nav_permissions.query),mediaRecorder:"function"==typeof(null==win?void 0:win.MediaRecorder),audioContext:"function"==typeof(null==win?void 0:win.AudioContext)||"function"==typeof(null==win?void 0:win.webkitAudioContext)}}function resolveCapabilityReason(capabilities){return"undefined"==typeof navigator?"unsupported-environment":capabilities.secureContext?!1===function(){var _doc_permissionsPolicy;if("undefined"!=typeof document){var doc=document,policy=null!=(_doc_permissionsPolicy=doc.permissionsPolicy)?_doc_permissionsPolicy:doc.featurePolicy;if("function"==typeof(null==policy?void 0:policy.allowsFeature))try{return policy.allowsFeature("microphone")}catch(unused){return}}}()?"permissions-policy":capabilities.getUserMedia||capabilities.legacyGetUserMedia?"ok":"no-getusermedia":"insecure-context"}exports.DateTime=DateTime,exports.addVc=function(url,codecs){void 0===codecs&&(codecs=["h264"]);var vc=getQueryVC(codecs||["h264"]),host=url.split("?")[0],query=url.split("?")[1];return query=(query||"").split("&").filter(function(item){return!/^vc=\d?/.test(item)}).join("&"),host+"?"+(query+=(query?"&":"")+"vc="+vc)},exports.checkMicrophoneSupport=function(options){void 0===options&&(options={});var _options_checkDevice=options.checkDevice,checkDevice=void 0===_options_checkDevice||_options_checkDevice,_options_checkPermission=options.checkPermission,checkPermission=void 0===_options_checkPermission||_options_checkPermission,_options_timeout=options.timeout,timeout=void 0===_options_timeout?2e3:_options_timeout,capabilities=getMicrophoneCapabilities(),capabilityReason=resolveCapabilityReason(capabilities);if("ok"!==capabilityReason)return Promise.resolve({supported:!1,available:!1,reason:capabilityReason,permission:"unknown",device:"unknown",willPrompt:!1,capabilities:capabilities});var permissionTask=checkPermission?function(timeout){var _getNavigatorLike,permissions=null==(_getNavigatorLike=getNavigatorLike())?void 0:_getNavigatorLike.permissions;if(!permissions||"function"!=typeof permissions.query)return Promise.resolve("unknown");try{return withTimeout(permissions.query({name:"microphone"}),timeout).then(function(status){return"granted"===(state=status.state)||"denied"===state||"prompt"===state?state:"unknown";var state},function(){return"unknown"})}catch(unused){return Promise.resolve("unknown")}}(timeout):Promise.resolve("unknown"),deviceTask=checkDevice?function(timeout){var _getNavigatorLike,pending,mediaDevices=null==(_getNavigatorLike=getNavigatorLike())?void 0:_getNavigatorLike.mediaDevices;if(!mediaDevices||"function"!=typeof mediaDevices.enumerateDevices)return Promise.resolve("unknown");try{pending=mediaDevices.enumerateDevices()}catch(unused){return Promise.resolve("unknown")}return withTimeout(pending,timeout).then(function(devices){return Array.isArray(devices)&&0!==devices.length?devices.some(function(device){return"audioinput"===(null==device?void 0:device.kind)})?"present":"absent":"unknown"},function(){return"unknown"})}(timeout):Promise.resolve("unknown");return Promise.all([permissionTask,deviceTask]).then(function(param){var permission=param[0],device=param[1],reason="ok";return"denied"===permission?reason="permission-denied":"absent"===device&&(reason="no-device"),{supported:!0,available:"ok"===reason,reason:reason,permission:permission,device:device,willPrompt:"granted"!==permission&&"denied"!==permission,capabilities:capabilities}})},exports.getMicrophoneCapabilities=getMicrophoneCapabilities,exports.getQuery=getQuery,exports.getQueryVC=getQueryVC,exports.getStaticPath=function(path,base){void 0===base&&(base="");var protocolReg=/^(https?:\/\/|^\/\/)/;if(""===path||void 0===path)return"";if(protocolReg.test(path))return path;path=path.replace(/\/+/g,"/"),base=protocolReg.test(base||"")?base:window.location.href;try{return new URL(path,base).href}catch(error){return path}},exports.isEmpty=function(param){return void 0===param||""===param||null===param},exports.isEzvizLiveUrl=function(url){if(isEzvizUrl(url)){var _url_split,path=url.split("?")[0],queryStr=(null==(_url_split=url.split("?"))?void 0:_url_split[1])||"";return/^http[s]?:\/\//.test(path)&&path.includes("/openlive/")||/^ezopen:\/\//.test(path)&&/\.live$/.test(path)||/\/live$/.test(path)&&queryStr&&/stream=\d+/.test(queryStr)&&queryStr.includes("dev=")&&queryStr.includes("ssn=")}return!1},exports.isEzvizPlaybackUrl=function(url){if(isEzvizUrl(url)){var _url_split,path=url.split("?")[0],queryStr=(null==(_url_split=url.split("?"))?void 0:_url_split[1])||"";return/^http[s]?:\/\//.test(path)&&path.includes("/openpb/")||/^ezopen:\/\//.test(path)&&/\.rec$/.test(path)||/\/(playback|cloudplayback)$/.test(path)&&queryStr&&/stream=\d+/.test(queryStr)&&queryStr.includes("dev=")&&queryStr.includes("ssn=")}return!1},exports.isEzvizUrl=isEzvizUrl,exports.isHttp=isHttp,exports.isMicrophoneSupported=function(){return"ok"===resolveCapabilityReason(getMicrophoneCapabilities())},exports.isMobile=function(agent){var _ref,_navigator,_navigator1,_navigator2,_window;return/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|Opera Mini)/i.test(null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)||/Macintosh/i.test(agent||(null==(_navigator1=navigator)?void 0:_navigator1.userAgent))&&(null!=(_ref=null==(_navigator2=navigator)?void 0:_navigator2.maxTouchPoints)?_ref:0)>1||!!(null==(_window=window)?void 0:_window.__IS_MOBILE_SIMULATOR__)},exports.isRealMobile=function(agent){var _ref,_navigator,ua=(null!=(_ref=null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)?_ref:"").toLowerCase();if(/ipad|tablet|playbook|silk|android(?!.*mobile)/i.test(ua))return!1;var hasTouch="ontouchstart"in window||navigator.maxTouchPoints>0;return/android|webos|iphone|ipod|blackberry|iemobile|opera mini/i.test(ua)&&hasTouch},exports.objectIsNull=function(obj){try{return"{}"===JSON.stringify(obj)}catch(error){return!1}},exports.parseEzopenUrl=parseEzopenUrl,exports.pick=function(obj,keys){return Object.entries(obj).reduce(function(acc,param){var key=param[0],value=param[1];return keys.includes(key)&&(acc[key]=value),acc},{})},exports.switchEzopenUrl=function(url,options){var _ref=null!=options?options:{},type=_ref.type,recType=_ref.recType,search=_ref.search,definition=_ref.definition,channelNo=_ref.channelNo,deviceSerial=_ref.deviceSerial,validateCode=_ref.validateCode,obj=parseEzopenUrl(url);if(search){var ns=Object.assign({},obj.searchParams,getQuery("?"+search.replace("?","")));search=Object.entries(ns).reduce(function(acc,param){var key=param[0],value=param[1];return""===value?acc:acc+=key+"="+encodeURIComponent(value)+"&"},"?").replace(/&$/,"")}else search=obj.search;return type=type||obj.type,recType=null!=recType?recType:obj.recType,definition=null!=definition?definition:obj.definition,channelNo=channelNo||obj.channelNo,deviceSerial=deviceSerial||obj.deviceSerial,validateCode=null!=validateCode?validateCode:obj.validateCode,obj.protocol+"//"+(validateCode?validateCode+"@":"")+obj.hostname+"/"+deviceSerial+"/"+channelNo+("rec"===type&&recType?"."+recType:"")+("live"===type&&"hd"===definition?"."+definition:"")+"."+type+search};
package/dist/index.umd.js CHANGED
@@ -1,7 +1,7 @@
1
1
  /*
2
- * @ezuikit/utils-tools v2.0.7
2
+ * @ezuikit/utils-tools v2.0.9
3
3
  * tools utils
4
- * Copyright (c) 2026-09-02 Ezviz-OpenBiz
4
+ * Copyright (c) 2026-11-03 Ezviz-OpenBiz
5
5
  * Released under the MIT License.
6
6
  */
7
- !function(global,factory){"object"==typeof exports&&"undefined"!=typeof module?factory(exports):"function"==typeof define&&define.amd?define(["exports"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).Tools={})}(this,(function(exports){"use strict";function isHttp(url){return/^http[s]?:\/\//.test(url)}var getQuery=function(url){var query=url.split("?")[1],obj={};if(query)for(var vars=query.split("&"),i=0;i<vars.length;i++){var pair=vars[i].split("=");obj[pair[0]]=decodeURIComponent(pair[1])}return obj};function parseEzopenUrl(url){var obj={};if(/^ezopen:\/\//.test(url)){if(url.includes("@")){var endIndex=url.indexOf("@"),startIndex=url.indexOf("//");obj.validateCode=url.substring(startIndex+2,endIndex),url=url.replace(obj.validateCode+"@","")}obj.protocol=url.split("//")[0],obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url;var pathnames=obj.pathname.split("/"),lastPath=pathnames[2].split(".");return obj.deviceSerial=pathnames[1],obj.channelNo=lastPath[0],obj.streamTypeIn=pathnames[2].includes(".hd.")?1:2,obj.type=lastPath[lastPath.length-1],"live"===obj.type&&(obj.definition=lastPath.length>2?lastPath[1]:"sd"),"rec"===obj.type&&pathnames[2]&&(obj.recType=pathnames[2].includes(".cloud.")?"cloud":""),obj.searchParams=getQuery(url),obj}if(isHttp(url))try{var u=new URL(url),file=u.pathname.split("/").pop();if(file&&["live","playback","cloudplayback","download"].includes(file)&&u.search.includes("dev=")&&u.search.includes("stream=")){var deviceSerial=u.searchParams.get("dev"),channelNo=u.searchParams.get("chn")||"1",sessionToken=u.searchParams.get("ssn"),stream=u.searchParams.get("stream"),streamTypeIn=Number(stream);if("https:"!==u.protocol||!deviceSerial||!channelNo||!sessionToken)return{};var searchParams={};u.searchParams.forEach((function(value,key){searchParams[key]=value})),obj.protocol=u.protocol,obj.search=u.search,obj.searchParams=searchParams,obj.pathname=u.pathname,obj.origin=u.origin,obj.href=url,obj.hostname=u.host,obj.deviceSerial=deviceSerial,obj.channelNo=channelNo,obj.streamTypeIn=streamTypeIn;var validateCode=u.searchParams.get("code");return validateCode&&(obj.validateCode=validateCode),"live"===file?(obj.type="live",obj.definition=1===streamTypeIn?"hd":"sd"):"playback"===file?(obj.type="rec",obj.recType=""):"cloudplayback"===file?(obj.type="rec",obj.recType="cloud"):obj.type="download",obj}if(file){var m=file.match(/^([^_]+)_(\d+)_(\d+)\./);if(m){var deviceSerial1=m[1],channelNo1=m[2],quality=m[3];return obj.deviceSerial=deviceSerial1,obj.channelNo=channelNo1,obj.streamTypeIn=+quality,u.searchParams.get("code")&&(obj.validateCode=u.searchParams.get("code")),obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.protocol=url.split("//")[0],obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url,obj.type="live",(url.includes("rec=local")||url.includes("rec=cloud"))&&(obj.type="rec",url.includes("rec=cloud")?obj.recType="cloud":obj.recType=""),"live"===obj.type&&(obj.definition="1"===quality?"hd":"sd"),obj.searchParams=getQuery(url),obj}}}catch(e){}return{}}var codec={h264:1,h265:2,h266:4,vp8:8,vp9:16,av1:32},getQueryVC=function(CODECS){return CODECS.reduce((function(acc,key){return key=key.toLowerCase(),acc+(codec[key]||0)}),0)};function _array_like_to_array(arr,len){(null==len||len>arr.length)&&(len=arr.length);for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _instanceof(left,right){return null!=right&&"undefined"!=typeof Symbol&&right[Symbol.hasInstance]?!!right[Symbol.hasInstance](left):left instanceof right}function _create_for_of_iterator_helper_loose(o,allowArrayLike){var it="undefined"!=typeof Symbol&&o[Symbol.iterator]||o["@@iterator"];if(it)return(it=it.call(o)).next.bind(it);if(Array.isArray(o)||(it=function(o,minLen){if(o){if("string"==typeof o)return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);return"Object"===n&&o.constructor&&(n=o.constructor.name),"Map"===n||"Set"===n?Array.from(n):"Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)?_array_like_to_array(o,minLen):void 0}}(o))||allowArrayLike){it&&(o=it);var i=0;return function(){return i>=o.length?{done:!0}:{done:!1,value:o[i++]}}}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 DateTime=function(){function DateTime(){}return DateTime.normalizeUnit=function(unit){return"year"===unit||"y"===unit||"年"===unit?"year":"month"===unit||"M"===unit||"月"===unit?"month":"day"===unit||"d"===unit||"日"===unit?"day":"hour"===unit||"h"===unit||"时"===unit?"hour":"minute"===unit||"m"===unit||"分"===unit?"minute":"second"},DateTime.daysInMonth=function(year,month){return new Date(year,month+1,0).getDate()},DateTime.shiftMonth=function(baseDate,months){var result=new Date(baseDate.getTime()),currentDate=result.getDate();result.setDate(1),result.setMonth(result.getMonth()+months);var maxDate=DateTime.daysInMonth(result.getFullYear(),result.getMonth());return result.setDate(Math.min(currentDate,maxDate)),result},DateTime.add=function(input,value,unit){if(void 0===unit&&(unit="day"),!Number.isFinite(value))throw new Error("Invalid value");var baseDate=DateTime.toDate(input),normalizedUnit=DateTime.normalizeUnit(unit);if("year"===normalizedUnit)return DateTime.shiftMonth(baseDate,12*value);if("month"===normalizedUnit)return DateTime.shiftMonth(baseDate,value);var result=new Date(baseDate.getTime());return result.setTime(result.getTime()+value*{day:864e5,hour:36e5,minute:6e4,second:1e3}[normalizedUnit]),result},DateTime.subtract=function(input,value,unit){return void 0===unit&&(unit="day"),DateTime.add(input,-value,unit)},DateTime.fillZero=function(num,len){return void 0===len&&(len=2),num.toString().padStart(len,"0")},DateTime.format=function(input,format){var date;if(_instanceof(input,Date))date=input;else{if("number"!=typeof input&&"string"!=typeof input)throw new Error("Invalid date input");date=DateTime.toDate(input+"")}for(var _step,result=format,_iterator=_create_for_of_iterator_helper_loose([[/(yyyy|YYYY)/g,function(){return DateTime.fillZero(date.getFullYear(),4)}],[/(yy|YY)/g,function(){return DateTime.fillZero(date.getFullYear()%100,2)}],[/(MM)/g,function(){return DateTime.fillZero(date.getMonth()+1,2)}],[/(M)/g,function(){return(date.getMonth()+1).toString()}],[/(dd|DD)/g,function(){return DateTime.fillZero(date.getDate(),2)}],[/(d|D)/g,function(){return date.getDate().toString()}],[/(HH|hh)/g,function(){return DateTime.fillZero(date.getHours(),2)}],[/(H|h)/g,function(){return date.getHours().toString()}],[/(mm)/g,function(){return DateTime.fillZero(date.getMinutes(),2)}],[/(m)/g,function(){return date.getMinutes().toString()}],[/(ss|SS)/g,function(){return DateTime.fillZero(date.getSeconds(),2)}],[/(s|S)/g,function(){return date.getSeconds().toString()}],[/(fff)/g,function(){return DateTime.fillZero(date.getMilliseconds(),3)}]]);!(_step=_iterator()).done;){var _step_value=_step.value,regexp=_step_value[0],fn=_step_value[1];result=result.replace(regexp,fn)}return result},DateTime.toDate=function(str){if(_instanceof(str,Date))return str;str=(str+"").trim().replace(/\/|\./gi,"-"),/^\d{4}$/.test(str)&&(str+="-01"),/^\d{4}-\d{2}$/.test(str)&&(str+="-01");try{return/^\d{4}-\d{2}-\d{2}$/.test(str)?new Date(+str.slice(0,4),+str.slice(5,7)-1,+str.slice(8,10),0,0,0):/^\d{8}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),0,0,0)):/^\d{14}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),+str.slice(8,10),+str.slice(10,12),+str.slice(12,14))):/^\d{13}$/.test(str)?new Date(Number(str)):/^\d{10}$/.test(str)?new Date(1e3*Number(str)):new Date(str)}catch(error){throw new Error("Invalid date string")}},DateTime.diff=function(date1,date2,type){void 0===type&&(type="second");var d1=DateTime.toDate(date1),d2=DateTime.toDate(date2);return"second"===type?Math.floor((d1.getTime()-d2.getTime())/1e3):"minute"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60):"hour"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60):"day"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60/24):Math.abs(d1.getTime()-d2.getTime())},DateTime}();exports.DateTime=DateTime,exports.addVc=function(url,codecs){void 0===codecs&&(codecs=["h264"]);var vc=getQueryVC(codecs||["h264"]),host=url.split("?")[0],query=url.split("?")[1];return query=(query||"").split("&").filter((function(item){return!/^vc=\d?/.test(item)})).join("&"),host+"?"+(query+=(query?"&":"")+"vc="+vc)},exports.getQuery=getQuery,exports.getQueryVC=getQueryVC,exports.getStaticPath=function(path,base){void 0===base&&(base="");var protocolReg=/^(https?:\/\/|^\/\/)/;if(""===path||void 0===path)return"";if(protocolReg.test(path))return path;path=path.replace(/\/+/g,"/"),base=protocolReg.test(base||"")?base:window.location.href;try{return new URL(path,base).href}catch(error){return path}},exports.isEmpty=function(param){return void 0===param||""===param||null===param},exports.isHttp=isHttp,exports.isMobile=function(agent){var _navigator,_navigator1,_navigator2,_window,_navigator_maxTouchPoints;return/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|Opera Mini)/i.test(null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)||/Macintosh/i.test(agent||(null==(_navigator1=navigator)?void 0:_navigator1.userAgent))&&(null!=(_navigator_maxTouchPoints=null==(_navigator2=navigator)?void 0:_navigator2.maxTouchPoints)?_navigator_maxTouchPoints:0)>1||!!(null==(_window=window)?void 0:_window.__IS_MOBILE_SIMULATOR__)},exports.isRealMobile=function(agent){var _navigator,_ref,ua=(null!=(_ref=null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)?_ref:"").toLowerCase();if(/ipad|tablet|playbook|silk|android(?!.*mobile)/i.test(ua))return!1;var hasTouch="ontouchstart"in window||navigator.maxTouchPoints>0;return/android|webos|iphone|ipod|blackberry|iemobile|opera mini/i.test(ua)&&hasTouch},exports.objectIsNull=function(obj){try{return"{}"===JSON.stringify(obj)}catch(error){return!1}},exports.parseEzopenUrl=parseEzopenUrl,exports.pick=function(obj,keys){return Object.entries(obj).reduce((function(acc,param){var key=param[0],value=param[1];return keys.includes(key)&&(acc[key]=value),acc}),{})},exports.switchEzopenUrl=function(url,options){var _ref=null!=options?options:{},type=_ref.type,recType=_ref.recType,search=_ref.search,definition=_ref.definition,channelNo=_ref.channelNo,deviceSerial=_ref.deviceSerial,validateCode=_ref.validateCode,obj=parseEzopenUrl(url);if(search){var ns=Object.assign({},obj.searchParams,getQuery("?"+search.replace("?","")));search=Object.entries(ns).reduce((function(acc,param){var key=param[0],value=param[1];return""===value?acc:acc+=key+"="+encodeURIComponent(value)+"&"}),"?").replace(/&$/,"")}else search=obj.search;return type=type||obj.type,recType=null!=recType?recType:obj.recType,definition=null!=definition?definition:obj.definition,channelNo=channelNo||obj.channelNo,deviceSerial=deviceSerial||obj.deviceSerial,validateCode=null!=validateCode?validateCode:obj.validateCode,obj.protocol+"//"+(validateCode?validateCode+"@":"")+obj.hostname+"/"+deviceSerial+"/"+channelNo+("rec"===type&&recType?"."+recType:"")+("live"===type&&"hd"===definition?"."+definition:"")+"."+type+search}}));
7
+ !function(global,factory){"object"==typeof exports&&"undefined"!=typeof module?factory(exports):"function"==typeof define&&define.amd?define(["exports"],factory):factory((global="undefined"!=typeof globalThis?globalThis:global||self).Tools={})}(this,function(exports){"use strict";function isHttp(url){return/^http[s]?:\/\//.test(url)}var getQuery=function(url){var query=url.split("?")[1],obj={};if(query)for(var vars=query.split("&"),i=0;i<vars.length;i++){var pair=vars[i].split("=");obj[pair[0]]=decodeURIComponent(pair[1])}return obj};function parseEzopenUrl(url){var obj={};if(/^ezopen:\/\//.test(url)){if(url.includes("@")){var endIndex=url.indexOf("@"),startIndex=url.indexOf("//");obj.validateCode=url.substring(startIndex+2,endIndex),url=url.replace(obj.validateCode+"@","")}obj.protocol=url.split("//")[0],obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url;var pathnames=obj.pathname.split("/"),lastPath=pathnames[2].split(".");return obj.deviceSerial=pathnames[1],obj.channelNo=lastPath[0],obj.streamTypeIn=pathnames[2].includes(".hd.")?1:2,obj.type=lastPath[lastPath.length-1],"live"===obj.type&&(obj.definition=lastPath.length>2?lastPath[1]:"sd"),"rec"===obj.type&&pathnames[2]&&(obj.recType=pathnames[2].includes(".cloud.")?"cloud":""),obj.searchParams=getQuery(url),obj}if(isHttp(url))try{var u=new URL(url),file=u.pathname.split("/").pop();if(file&&["live","playback","cloudplayback","download"].includes(file)&&u.search.includes("dev=")&&u.search.includes("stream=")){var deviceSerial=u.searchParams.get("dev"),channelNo=u.searchParams.get("chn")||"1",sessionToken=u.searchParams.get("ssn"),stream=u.searchParams.get("stream"),streamTypeIn=Number(stream);if(!("https:"===u.protocol&&deviceSerial&&channelNo&&sessionToken&&streamTypeIn))return{};var searchParams={};u.searchParams.forEach(function(value,key){searchParams[key]=value}),obj.protocol=u.protocol,obj.search=u.search,obj.searchParams=searchParams,obj.pathname=u.pathname,obj.origin=u.origin,obj.href=url,obj.hostname=u.host,obj.deviceSerial=deviceSerial,obj.channelNo=channelNo,obj.streamTypeIn=streamTypeIn;var validateCode=u.searchParams.get("code");return validateCode&&(obj.validateCode=validateCode),"live"===file?(obj.type="live",obj.definition=1===streamTypeIn?"hd":"sd"):"playback"===file?(obj.type="rec",obj.recType=""):"cloudplayback"===file?(obj.type="rec",obj.recType="cloud"):obj.type="download",obj}if(file){var m=file.match(/^([^_]+)_(\d+)_(\d+)\./);if(m){var deviceSerial1=m[1],channelNo1=m[2],quality=m[3];return obj.deviceSerial=deviceSerial1,obj.channelNo=channelNo1,obj.streamTypeIn=+quality,u.searchParams.get("code")&&(obj.validateCode=u.searchParams.get("code")),obj.search=url.split("?")[1]?"?"+url.split("?")[1]:"",obj.protocol=url.split("//")[0],obj.hostname=url.split("/")[2],obj.origin=obj.protocol+"//"+obj.hostname,obj.pathname=url.split("?")[0].replace(obj.origin,""),obj.href=url,obj.type="live",(url.includes("rec=local")||url.includes("rec=cloud"))&&(obj.type="rec",url.includes("rec=cloud")?obj.recType="cloud":obj.recType=""),"live"===obj.type&&(obj.definition="1"===quality?"hd":"sd"),obj.searchParams=getQuery(url),obj}}}catch(e){}return{}}function isEzvizUrl(url){var _url_split,path=url.split("?")[0],queryStr=(null==(_url_split=url.split("?"))?void 0:_url_split[1])||"";if(/^http[s]?:\/\//.test(path)&&/\/openlive\/|\/openpb\//.test(path)&&(/\.flv$/i.test(path)||/\.m3u8$/i.test(path)||/_\d+$/.test(path))){var newPath=path.replace(/\.flv|\.m3u8/gi,"");if(/_\d+_\d+$/.test(newPath))return!0}return/^ezopen:\/\//.test(path)||/\/(playback|cloudplayback|live)$/.test(path)&&queryStr&&/stream=\d+/.test(queryStr)&&queryStr.includes("dev=")&&queryStr.includes("ssn=")}var codec={h264:1,h265:2,h266:4,vp8:8,vp9:16,av1:32},getQueryVC=function(CODECS){return CODECS.reduce(function(acc,key){return key=key.toLowerCase(),acc+(codec[key]||0)},0)};function _array_like_to_array(arr,len){(null==len||len>arr.length)&&(len=arr.length);for(var i=0,arr2=new Array(len);i<len;i++)arr2[i]=arr[i];return arr2}function _create_for_of_iterator_helper_loose(o,allowArrayLike){var it="undefined"!=typeof Symbol&&o[Symbol.iterator]||o["@@iterator"];if(it)return(it=it.call(o)).next.bind(it);if(Array.isArray(o)||(it=function(o,minLen){if(!o)return;if("string"==typeof o)return _array_like_to_array(o,minLen);var n=Object.prototype.toString.call(o).slice(8,-1);"Object"===n&&o.constructor&&(n=o.constructor.name);if("Map"===n||"Set"===n)return Array.from(n);if("Arguments"===n||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n))return _array_like_to_array(o,minLen)}(o))||allowArrayLike){it&&(o=it);var i=0;return function(){return i>=o.length?{done:!0}:{done:!1,value:o[i++]}}}throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _instanceof(left,right){return null!=right&&"undefined"!=typeof Symbol&&right[Symbol.hasInstance]?!!right[Symbol.hasInstance](left):left instanceof right}var DateTime=function(){function DateTime(){}return DateTime.normalizeUnit=function(unit){return"year"===unit||"y"===unit||"年"===unit?"year":"month"===unit||"M"===unit||"月"===unit?"month":"day"===unit||"d"===unit||"日"===unit?"day":"hour"===unit||"h"===unit||"时"===unit?"hour":"minute"===unit||"m"===unit||"分"===unit?"minute":"second"},DateTime.daysInMonth=function(year,month){return new Date(year,month+1,0).getDate()},DateTime.shiftMonth=function(baseDate,months){var result=new Date(baseDate.getTime()),currentDate=result.getDate();result.setDate(1),result.setMonth(result.getMonth()+months);var maxDate=DateTime.daysInMonth(result.getFullYear(),result.getMonth());return result.setDate(Math.min(currentDate,maxDate)),result},DateTime.add=function(input,value,unit){if(void 0===unit&&(unit="day"),!Number.isFinite(value))throw new Error("Invalid value");var baseDate=DateTime.toDate(input),normalizedUnit=DateTime.normalizeUnit(unit);if("year"===normalizedUnit)return DateTime.shiftMonth(baseDate,12*value);if("month"===normalizedUnit)return DateTime.shiftMonth(baseDate,value);var result=new Date(baseDate.getTime());return result.setTime(result.getTime()+value*{day:864e5,hour:36e5,minute:6e4,second:1e3}[normalizedUnit]),result},DateTime.subtract=function(input,value,unit){return void 0===unit&&(unit="day"),DateTime.add(input,-value,unit)},DateTime.fillZero=function(num,len){return void 0===len&&(len=2),num.toString().padStart(len,"0")},DateTime.format=function(input,format){var date;if(_instanceof(input,Date))date=input;else{if("number"!=typeof input&&"string"!=typeof input)throw new Error("Invalid date input");date=DateTime.toDate(input+"")}for(var _step,result=format,_iterator=_create_for_of_iterator_helper_loose([[/(yyyy|YYYY)/g,function(){return DateTime.fillZero(date.getFullYear(),4)}],[/(yy|YY)/g,function(){return DateTime.fillZero(date.getFullYear()%100,2)}],[/(MM)/g,function(){return DateTime.fillZero(date.getMonth()+1,2)}],[/(M)/g,function(){return(date.getMonth()+1).toString()}],[/(dd|DD)/g,function(){return DateTime.fillZero(date.getDate(),2)}],[/(d|D)/g,function(){return date.getDate().toString()}],[/(HH|hh)/g,function(){return DateTime.fillZero(date.getHours(),2)}],[/(H|h)/g,function(){return date.getHours().toString()}],[/(mm)/g,function(){return DateTime.fillZero(date.getMinutes(),2)}],[/(m)/g,function(){return date.getMinutes().toString()}],[/(ss|SS)/g,function(){return DateTime.fillZero(date.getSeconds(),2)}],[/(s|S)/g,function(){return date.getSeconds().toString()}],[/(fff)/g,function(){return DateTime.fillZero(date.getMilliseconds(),3)}]]);!(_step=_iterator()).done;){var _step_value=_step.value,regexp=_step_value[0],fn=_step_value[1];result=result.replace(regexp,fn)}return result},DateTime.toDate=function(str){if(_instanceof(str,Date))return str;str=(str+"").trim().replace(/\/|\./gi,"-"),/^\d{4}$/.test(str)&&(str+="-01"),/^\d{4}-\d{2}$/.test(str)&&(str+="-01");try{return/^\d{4}-\d{2}-\d{2}$/.test(str)?new Date(+str.slice(0,4),+str.slice(5,7)-1,+str.slice(8,10),0,0,0):/^\d{8}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),0,0,0)):/^\d{14}$/.test(str)?(str+="",new Date(+str.slice(0,4),+str.slice(4,6)-1,+str.slice(6,8),+str.slice(8,10),+str.slice(10,12),+str.slice(12,14))):/^\d{13}$/.test(str)?new Date(Number(str)):/^\d{10}$/.test(str)?new Date(1e3*Number(str)):new Date(str)}catch(error){throw new Error("Invalid date string")}},DateTime.diff=function(date1,date2,type){void 0===type&&(type="second");var d1=DateTime.toDate(date1),d2=DateTime.toDate(date2);return"second"===type?Math.floor((d1.getTime()-d2.getTime())/1e3):"minute"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60):"hour"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60):"day"===type?Math.floor((d1.getTime()-d2.getTime())/1e3/60/60/24):Math.abs(d1.getTime()-d2.getTime())},DateTime}();function getNavigatorLike(){if("undefined"!=typeof navigator)return navigator}function getWindowLike(){if("undefined"!=typeof window)return window}function detectSecureContext(){var win=getWindowLike();if("boolean"==typeof(null==win?void 0:win.isSecureContext))return win.isSecureContext;if("undefined"==typeof location)return!1;if("https:"===location.protocol||"file:"===location.protocol)return!0;var hostname=location.hostname||"";return"localhost"===hostname||/\.localhost$/.test(hostname)||"127.0.0.1"===hostname||"[::1]"===hostname||"::1"===hostname}function withTimeout(promise,timeout){return timeout>0?new Promise(function(resolve,reject){var settled=!1,timer=setTimeout(function(){settled||(settled=!0,reject(new Error("[microphone] detect timeout")))},timeout),finish=function(run){settled||(settled=!0,clearTimeout(timer),run())};promise.then(function(value){return finish(function(){return resolve(value)})},function(error){return finish(function(){return reject(error)})})}):promise}function getMicrophoneCapabilities(){var _nav_permissions,nav=getNavigatorLike(),win=getWindowLike(),mediaDevices=null==nav?void 0:nav.mediaDevices;return{secureContext:detectSecureContext(),mediaDevices:!!mediaDevices,getUserMedia:"function"==typeof(null==mediaDevices?void 0:mediaDevices.getUserMedia),legacyGetUserMedia:"function"==typeof(null==nav?void 0:nav.getUserMedia)||"function"==typeof(null==nav?void 0:nav.webkitGetUserMedia)||"function"==typeof(null==nav?void 0:nav.mozGetUserMedia)||"function"==typeof(null==nav?void 0:nav.msGetUserMedia),enumerateDevices:"function"==typeof(null==mediaDevices?void 0:mediaDevices.enumerateDevices),permissionsQuery:"function"==typeof(null==nav||null==(_nav_permissions=nav.permissions)?void 0:_nav_permissions.query),mediaRecorder:"function"==typeof(null==win?void 0:win.MediaRecorder),audioContext:"function"==typeof(null==win?void 0:win.AudioContext)||"function"==typeof(null==win?void 0:win.webkitAudioContext)}}function resolveCapabilityReason(capabilities){return"undefined"==typeof navigator?"unsupported-environment":capabilities.secureContext?!1===function(){var _doc_permissionsPolicy;if("undefined"!=typeof document){var doc=document,policy=null!=(_doc_permissionsPolicy=doc.permissionsPolicy)?_doc_permissionsPolicy:doc.featurePolicy;if("function"==typeof(null==policy?void 0:policy.allowsFeature))try{return policy.allowsFeature("microphone")}catch(unused){return}}}()?"permissions-policy":capabilities.getUserMedia||capabilities.legacyGetUserMedia?"ok":"no-getusermedia":"insecure-context"}exports.DateTime=DateTime,exports.addVc=function(url,codecs){void 0===codecs&&(codecs=["h264"]);var vc=getQueryVC(codecs||["h264"]),host=url.split("?")[0],query=url.split("?")[1];return query=(query||"").split("&").filter(function(item){return!/^vc=\d?/.test(item)}).join("&"),host+"?"+(query+=(query?"&":"")+"vc="+vc)},exports.checkMicrophoneSupport=function(options){void 0===options&&(options={});var _options_checkDevice=options.checkDevice,checkDevice=void 0===_options_checkDevice||_options_checkDevice,_options_checkPermission=options.checkPermission,checkPermission=void 0===_options_checkPermission||_options_checkPermission,_options_timeout=options.timeout,timeout=void 0===_options_timeout?2e3:_options_timeout,capabilities=getMicrophoneCapabilities(),capabilityReason=resolveCapabilityReason(capabilities);if("ok"!==capabilityReason)return Promise.resolve({supported:!1,available:!1,reason:capabilityReason,permission:"unknown",device:"unknown",willPrompt:!1,capabilities:capabilities});var permissionTask=checkPermission?function(timeout){var _getNavigatorLike,permissions=null==(_getNavigatorLike=getNavigatorLike())?void 0:_getNavigatorLike.permissions;if(!permissions||"function"!=typeof permissions.query)return Promise.resolve("unknown");try{return withTimeout(permissions.query({name:"microphone"}),timeout).then(function(status){return"granted"===(state=status.state)||"denied"===state||"prompt"===state?state:"unknown";var state},function(){return"unknown"})}catch(unused){return Promise.resolve("unknown")}}(timeout):Promise.resolve("unknown"),deviceTask=checkDevice?function(timeout){var _getNavigatorLike,pending,mediaDevices=null==(_getNavigatorLike=getNavigatorLike())?void 0:_getNavigatorLike.mediaDevices;if(!mediaDevices||"function"!=typeof mediaDevices.enumerateDevices)return Promise.resolve("unknown");try{pending=mediaDevices.enumerateDevices()}catch(unused){return Promise.resolve("unknown")}return withTimeout(pending,timeout).then(function(devices){return Array.isArray(devices)&&0!==devices.length?devices.some(function(device){return"audioinput"===(null==device?void 0:device.kind)})?"present":"absent":"unknown"},function(){return"unknown"})}(timeout):Promise.resolve("unknown");return Promise.all([permissionTask,deviceTask]).then(function(param){var permission=param[0],device=param[1],reason="ok";return"denied"===permission?reason="permission-denied":"absent"===device&&(reason="no-device"),{supported:!0,available:"ok"===reason,reason:reason,permission:permission,device:device,willPrompt:"granted"!==permission&&"denied"!==permission,capabilities:capabilities}})},exports.getMicrophoneCapabilities=getMicrophoneCapabilities,exports.getQuery=getQuery,exports.getQueryVC=getQueryVC,exports.getStaticPath=function(path,base){void 0===base&&(base="");var protocolReg=/^(https?:\/\/|^\/\/)/;if(""===path||void 0===path)return"";if(protocolReg.test(path))return path;path=path.replace(/\/+/g,"/"),base=protocolReg.test(base||"")?base:window.location.href;try{return new URL(path,base).href}catch(error){return path}},exports.isEmpty=function(param){return void 0===param||""===param||null===param},exports.isEzvizLiveUrl=function(url){if(isEzvizUrl(url)){var _url_split,path=url.split("?")[0],queryStr=(null==(_url_split=url.split("?"))?void 0:_url_split[1])||"";return/^http[s]?:\/\//.test(path)&&path.includes("/openlive/")||/^ezopen:\/\//.test(path)&&/\.live$/.test(path)||/\/live$/.test(path)&&queryStr&&/stream=\d+/.test(queryStr)&&queryStr.includes("dev=")&&queryStr.includes("ssn=")}return!1},exports.isEzvizPlaybackUrl=function(url){if(isEzvizUrl(url)){var _url_split,path=url.split("?")[0],queryStr=(null==(_url_split=url.split("?"))?void 0:_url_split[1])||"";return/^http[s]?:\/\//.test(path)&&path.includes("/openpb/")||/^ezopen:\/\//.test(path)&&/\.rec$/.test(path)||/\/(playback|cloudplayback)$/.test(path)&&queryStr&&/stream=\d+/.test(queryStr)&&queryStr.includes("dev=")&&queryStr.includes("ssn=")}return!1},exports.isEzvizUrl=isEzvizUrl,exports.isHttp=isHttp,exports.isMicrophoneSupported=function(){return"ok"===resolveCapabilityReason(getMicrophoneCapabilities())},exports.isMobile=function(agent){var _ref,_navigator,_navigator1,_navigator2,_window;return/(phone|pad|pod|iPhone|iPod|ios|iPad|Android|Mobile|BlackBerry|IEMobile|MQQBrowser|JUC|Fennec|wOSBrowser|BrowserNG|WebOS|Symbian|Windows Phone|Opera Mini)/i.test(null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)||/Macintosh/i.test(agent||(null==(_navigator1=navigator)?void 0:_navigator1.userAgent))&&(null!=(_ref=null==(_navigator2=navigator)?void 0:_navigator2.maxTouchPoints)?_ref:0)>1||!!(null==(_window=window)?void 0:_window.__IS_MOBILE_SIMULATOR__)},exports.isRealMobile=function(agent){var _ref,_navigator,ua=(null!=(_ref=null!=agent?agent:null==(_navigator=navigator)?void 0:_navigator.userAgent)?_ref:"").toLowerCase();if(/ipad|tablet|playbook|silk|android(?!.*mobile)/i.test(ua))return!1;var hasTouch="ontouchstart"in window||navigator.maxTouchPoints>0;return/android|webos|iphone|ipod|blackberry|iemobile|opera mini/i.test(ua)&&hasTouch},exports.objectIsNull=function(obj){try{return"{}"===JSON.stringify(obj)}catch(error){return!1}},exports.parseEzopenUrl=parseEzopenUrl,exports.pick=function(obj,keys){return Object.entries(obj).reduce(function(acc,param){var key=param[0],value=param[1];return keys.includes(key)&&(acc[key]=value),acc},{})},exports.switchEzopenUrl=function(url,options){var _ref=null!=options?options:{},type=_ref.type,recType=_ref.recType,search=_ref.search,definition=_ref.definition,channelNo=_ref.channelNo,deviceSerial=_ref.deviceSerial,validateCode=_ref.validateCode,obj=parseEzopenUrl(url);if(search){var ns=Object.assign({},obj.searchParams,getQuery("?"+search.replace("?","")));search=Object.entries(ns).reduce(function(acc,param){var key=param[0],value=param[1];return""===value?acc:acc+=key+"="+encodeURIComponent(value)+"&"},"?").replace(/&$/,"")}else search=obj.search;return type=type||obj.type,recType=null!=recType?recType:obj.recType,definition=null!=definition?definition:obj.definition,channelNo=channelNo||obj.channelNo,deviceSerial=deviceSerial||obj.deviceSerial,validateCode=null!=validateCode?validateCode:obj.validateCode,obj.protocol+"//"+(validateCode?validateCode+"@":"")+obj.hostname+"/"+deviceSerial+"/"+channelNo+("rec"===type&&recType?"."+recType:"")+("live"===type&&"hd"===definition?"."+definition:"")+"."+type+search}});
@@ -1,5 +1,6 @@
1
1
  import { parseEzopenUrl, switchEzopenUrl, type EzopenURL, type SwitchEzpoenOptions, type EzopenType, type EzopenRecType, type EzopenDefinition } from './ezopenUrl';
2
2
  import { isHttp } from './isHttp';
3
+ import { isEzvizUrl, isEzvizLiveUrl, isEzvizPlaybackUrl } from './isEzviz';
3
4
  import { isMobile, isRealMobile } from './isMobile';
4
5
  import { getQuery } from './query';
5
6
  import { pick } from './pick';
@@ -7,4 +8,5 @@ import { getStaticPath } from './getStaticPath';
7
8
  import { addVc, getQueryVC } from './addVc';
8
9
  import { isEmpty, objectIsNull } from './null';
9
10
  import DateTime, { type DateLike, type DateUnit } from './datetime';
10
- export { parseEzopenUrl, switchEzopenUrl, type EzopenURL, type SwitchEzpoenOptions, type EzopenType, type EzopenRecType, type EzopenDefinition, type DateLike, type DateUnit, isHttp, isMobile, isRealMobile, getQuery, pick, getStaticPath, addVc, getQueryVC, isEmpty, objectIsNull, DateTime, };
11
+ import { isMicrophoneSupported, checkMicrophoneSupport, getMicrophoneCapabilities, type MicrophonePermissionState, type MicrophoneDeviceState, type MicrophoneUnavailableReason, type MicrophoneCapabilities, type CheckMicrophoneSupportOptions, type MicrophoneSupportResult } from './microphone';
12
+ export { parseEzopenUrl, switchEzopenUrl, type EzopenURL, type SwitchEzpoenOptions, type EzopenType, type EzopenRecType, type EzopenDefinition, type DateLike, type DateUnit, isHttp, isEzvizUrl, isEzvizLiveUrl, isEzvizPlaybackUrl, isMobile, isRealMobile, getQuery, pick, getStaticPath, addVc, getQueryVC, isEmpty, objectIsNull, DateTime, isMicrophoneSupported, checkMicrophoneSupport, getMicrophoneCapabilities, type MicrophonePermissionState, type MicrophoneDeviceState, type MicrophoneUnavailableReason, type MicrophoneCapabilities, type CheckMicrophoneSupportOptions, type MicrophoneSupportResult, };
@@ -0,0 +1,68 @@
1
+ /**
2
+ * 判断是否为萤石播放地址。
3
+ *
4
+ * @remarks
5
+ * 只校验 `?` 之前的部分,查询参数不参与判断。满足以下任一条件即视为萤石播放地址:
6
+ *
7
+ * - `ezopen://` 协议地址(私有流),只校验协议头
8
+ * - `http(s)://` 标准流地址:路径包含 `/openlive/`(直播)或 `/openpb/`(回放),
9
+ * 且文件名形如 `{设备序列号}_{通道号}_{码流类型}.flv` 或 `{设备序列号}_{通道号}_{码流类型}.m3u8`
10
+ *
11
+ * @param url - 待判断的播放地址
12
+ * @returns 是萤石播放地址时返回 `true`,否则返回 `false`
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * isEzvizUrl('ezopen://open.ys7.com/BW3143164/1.hd.live'); // true
17
+ * isEzvizUrl('https://open.ys7.com/v3/openlive/BW3143164_1_1.m3u8'); // true
18
+ * isEzvizUrl('https://rtmp05open.ys7.com:9188/v3/openpb/BW3143164_1_1.flv?rec=local'); // true
19
+ * isEzvizUrl('wss://aljnvip.ys7.com:20006/live?dev=BC7799091&serial=BC7799091&chn=1&ssn=dv.77ytj17830c5q9wg5kgbvu0u4tgrz9xm6zmt3j48-1sfuzv4acf-1dx57hp-g6peofs4beq3ka0bqidlo-5&auth=1&cln=100&timeZone=0&r=0.1891235998016395&stream=1'); // true
20
+ * isEzvizUrl('wss://aljnvip.ys7.com:20006/playback?dev=BC7799091&serial=BC7799091&chn=1&ssn=dv.77ytj17830c5q9wg5kgbvu0u4tgrz9xm6zmt3j48-1sfuzv4acf-1dx57hp-g6peofs4beq3ka0bqidlo-5&auth=1&cln=100&begin=20261030T000000Z&end=20261030T235959Z&timeZone=0&recSlice=[{\"downloadPath\":\"alicloud.ys7.com:32723\",\"ownerId\":\"openteam\",\"iStorageVersion\":2,\"startTime\":1793289600000,\"endTime\":1793375999000,\"videoType\":2}]&r=0.1891235998016395&stream=1'); // true
21
+ * isEzvizUrl('wss://aljnvip.ys7.com:20006/cloudplayback?dev=BC7799091&serial=BC7799091&chn=1&ssn=dv.77ytj17830c5q9wg5kgbvu0u4tgrz9xm6zmt3j48-1sfuzv4acf-1dx57hp-g6peofs4beq3ka0bqidlo-5&auth=1&cln=100&begin=20261030T000000Z&end=20261030T235959Z&timeZone=0&recSlice=[{\"downloadPath\":\"alicloud.ys7.com:32723\",\"ownerId\":\"openteam\",\"iStorageVersion\":2,\"startTime\":1793289600000,\"endTime\":1793375999000,\"videoType\":2}]&r=0.1891235998016395&stream=1'); // true
22
+ * isEzvizUrl('/live?dev=BC7799091&serial=BC7799091&chn=1&ssn=dv.77ytj17830c5q9wg5kgbvu0u4tgrz9xm6zmt3j48-1sfuzv4acf-1dx57hp-g6peofs4beq3ka0bqidlo-5&auth=1&cln=100&timeZone=0&r=0.1891235998016395&stream=1'); // true
23
+ * isEzvizUrl('/playback?dev=BC7799091&serial=BC7799091&chn=1&ssn=dv.77ytj17830c5q9wg5kgbvu0u4tgrz9xm6zmt3j48-1sfuzv4acf-1dx57hp-g6peofs4beq3ka0bqidlo-5&auth=1&cln=100&begin=20261030T000000Z&end=20261030T235959Z&timeZone=0&recSlice=[{\"downloadPath\":\"alicloud.ys7.com:32723\",\"ownerId\":\"openteam\",\"iStorageVersion\":2,\"startTime\":1793289600000,\"endTime\":1793375999000,\"videoType\":2}]&r=0.1891235998016395&stream=1'); // true
24
+ * isEzvizUrl('/cloudplayback?dev=BC7799091&serial=BC7799091&chn=1&ssn=dv.77ytj17830c5q9wg5kgbvu0u4tgrz9xm6zmt3j48-1sfuzv4acf-1dx57hp-g6peofs4beq3ka0bqidlo-5&auth=1&cln=100&begin=20261030T000000Z&end=20261030T235959Z&timeZone=0&recSlice=[{\"downloadPath\":\"alicloud.ys7.com:32723\",\"ownerId\":\"openteam\",\"iStorageVersion\":2,\"startTime\":1793289600000,\"endTime\":1793375999000,\"videoType\":2}]&r=0.1891235998016395&stream=1'); // true
25
+ * isEzvizUrl('https://open.ys7.com/console/setezopenlive.html'); // false
26
+ * ```
27
+ */
28
+ export declare function isEzvizUrl(url: string): boolean;
29
+ /**
30
+ * 判断是否为萤石预览(直播)地址,包括私有流(ezopen)和标准流(flv/hls)。
31
+ *
32
+ * @remarks
33
+ * 需先满足 {@link isEzvizUrl},再按以下规则判断:
34
+ *
35
+ * - `ezopen://` 地址:路径以 `.live` 结尾
36
+ * - `http(s)://` 地址:路径包含 `/openlive/`
37
+ *
38
+ * @param url - 待判断的播放地址
39
+ * @returns 是萤石直播地址时返回 `true`,否则返回 `false`
40
+ *
41
+ * @example
42
+ * ```typescript
43
+ * isEzvizLiveUrl('ezopen://open.ys7.com/BW3143164/1.hd.live'); // true
44
+ * isEzvizLiveUrl('https://open.ys7.com/v3/openlive/llhls/BW3143164_1_1.m3u8'); // true
45
+ * isEzvizLiveUrl('ezopen://open.ys7.com/BW3143164/1.rec'); // false
46
+ * ```
47
+ */
48
+ export declare function isEzvizLiveUrl(url: string): boolean;
49
+ /**
50
+ * 判断是否为萤石回放地址,包括私有流(ezopen)和标准流(flv/hls)。
51
+ *
52
+ * @remarks
53
+ * 需先满足 {@link isEzvizUrl},再按以下规则判断:
54
+ *
55
+ * - `ezopen://` 地址:路径以 `.rec` 结尾(如 `1.rec`、`1.cloud.rec`、`1.hd.local.rec`)
56
+ * - `http(s)://` 地址:路径包含 `/openpb/`
57
+ *
58
+ * @param url - 待判断的播放地址
59
+ * @returns 是萤石回放地址时返回 `true`,否则返回 `false`
60
+ *
61
+ * @example
62
+ * ```typescript
63
+ * isEzvizPlaybackUrl('ezopen://open.ys7.com/BW3143164/1.cloud.rec'); // true
64
+ * isEzvizPlaybackUrl('https://open.ys7.com/v3/openpb/llhls/BW3143164_1_1.m3u8?rec=local'); // true
65
+ * isEzvizPlaybackUrl('ezopen://open.ys7.com/BW3143164/1.hd.live'); // false
66
+ * ```
67
+ */
68
+ export declare function isEzvizPlaybackUrl(url: string): boolean;
@@ -0,0 +1,245 @@
1
+ /**
2
+ * 麦克风权限状态。
3
+ *
4
+ * @remarks
5
+ * - `granted`:已授权,调用 `getUserMedia` 不会弹窗
6
+ * - `denied`:已被用户或系统策略拒绝,调用 `getUserMedia` 会立即 reject
7
+ * - `prompt`:尚未决定,调用 `getUserMedia` 会弹窗
8
+ * - `unknown`:当前浏览器无法查询权限状态(Safari 全系、Firefox 均不支持查询
9
+ * `microphone` 权限),不代表没有权限
10
+ *
11
+ * @since 2.0.8
12
+ */
13
+ export type MicrophonePermissionState = 'granted' | 'denied' | 'prompt' | 'unknown';
14
+ /**
15
+ * 麦克风设备存在状态。
16
+ *
17
+ * @remarks
18
+ * - `present`:设备列表中存在 `audioinput`
19
+ * - `absent`:设备列表非空但不含 `audioinput`,基本可以确认没有麦克风
20
+ * - `unknown`:无法枚举设备,或设备列表为空。Safari 未授权时、Firefox 开启
21
+ * `resistFingerprinting` 时、Brave 等隐私浏览器都可能返回空列表,**空列表不等于没有麦克风**
22
+ *
23
+ * @since 2.0.8
24
+ */
25
+ export type MicrophoneDeviceState = 'present' | 'absent' | 'unknown';
26
+ /**
27
+ * 麦克风不可用的原因。
28
+ *
29
+ * @remarks
30
+ * 按判定顺序返回首个命中的原因,`ok` 表示通过全部检查。
31
+ *
32
+ * - `ok`:可以尝试调用 `getUserMedia`
33
+ * - `unsupported-environment`:非浏览器环境(SSR、Web Worker)
34
+ * - `insecure-context`:非安全上下文,即非 `https` 且非 `localhost`。此时 Chromium 下
35
+ * `navigator.mediaDevices` 直接为 `undefined`
36
+ * - `permissions-policy`:页面被嵌在 iframe 中且未声明 `allow="microphone"`
37
+ * - `no-getusermedia`:浏览器不提供 `getUserMedia`,如 iOS 14.3 之前的 WKWebView
38
+ * - `permission-denied`:权限已被拒绝
39
+ * - `no-device`:确认没有麦克风输入设备
40
+ *
41
+ * @since 2.0.8
42
+ */
43
+ export type MicrophoneUnavailableReason = 'ok' | 'unsupported-environment' | 'insecure-context' | 'permissions-policy' | 'no-getusermedia' | 'permission-denied' | 'no-device';
44
+ /**
45
+ * 麦克风相关 API 的能力明细,全部为同步探测结果。
46
+ *
47
+ * @since 2.0.8
48
+ */
49
+ export interface MicrophoneCapabilities {
50
+ /** 是否处于安全上下文(`https`、`localhost` 或 `file:`) */
51
+ secureContext: boolean;
52
+ /** `navigator.mediaDevices` 是否存在 */
53
+ mediaDevices: boolean;
54
+ /** 标准 `navigator.mediaDevices.getUserMedia` 是否可用 */
55
+ getUserMedia: boolean;
56
+ /** 带前缀的旧版 `navigator.getUserMedia` 是否可用(老版 Android / UC 内核) */
57
+ legacyGetUserMedia: boolean;
58
+ /** `navigator.mediaDevices.enumerateDevices` 是否可用 */
59
+ enumerateDevices: boolean;
60
+ /**
61
+ * `navigator.permissions.query` 是否存在
62
+ *
63
+ * @remarks
64
+ * 仅表示 API 存在,不代表支持查询 `microphone`。实际查询结果见
65
+ * {@link MicrophoneSupportResult.permission}
66
+ */
67
+ permissionsQuery: boolean;
68
+ /** `MediaRecorder` 是否可用(需要录音时关注) */
69
+ mediaRecorder: boolean;
70
+ /** `AudioContext` 是否可用(需要音量检测、重采样等处理时关注) */
71
+ audioContext: boolean;
72
+ }
73
+ /**
74
+ * {@link checkMicrophoneSupport} 的配置项。
75
+ *
76
+ * @since 2.0.8
77
+ */
78
+ export interface CheckMicrophoneSupportOptions {
79
+ /**
80
+ * 是否枚举设备以判断麦克风是否存在。
81
+ *
82
+ * @defaultValue true
83
+ */
84
+ checkDevice?: boolean;
85
+ /**
86
+ * 是否查询权限状态。
87
+ *
88
+ * @defaultValue true
89
+ */
90
+ checkPermission?: boolean;
91
+ /**
92
+ * 异步探测的超时时间,单位毫秒。小于等于 0 表示不限制。
93
+ *
94
+ * @remarks
95
+ * 部分 Android WebView(含 X5 内核)下 `enumerateDevices()` 可能长时间不 settle,
96
+ * 超时后对应结果降级为 `unknown`。
97
+ *
98
+ * @defaultValue 2000
99
+ */
100
+ timeout?: number;
101
+ }
102
+ /**
103
+ * 麦克风支持情况的检测结果。
104
+ *
105
+ * @since 2.0.8
106
+ */
107
+ export interface MicrophoneSupportResult {
108
+ /**
109
+ * 环境是否具备采集麦克风的能力。
110
+ *
111
+ * @remarks
112
+ * 只看 API 与安全上下文,不含权限与设备状态。适合用来决定「要不要渲染对讲入口」。
113
+ */
114
+ supported: boolean;
115
+ /**
116
+ * 综合判定,当前调用 `getUserMedia` 是否有望成功。
117
+ *
118
+ * @remarks
119
+ * 等价于 `supported` 且权限未被拒绝且确认有设备。适合用来决定「要不要真的发起采集」。
120
+ */
121
+ available: boolean;
122
+ /** 导致 `available` 为 `false` 的首要原因,可用时为 `ok` */
123
+ reason: MicrophoneUnavailableReason;
124
+ /** 权限状态,无法查询时为 `unknown` */
125
+ permission: MicrophonePermissionState;
126
+ /** 麦克风设备状态,无法确认时为 `unknown` */
127
+ device: MicrophoneDeviceState;
128
+ /** 调用 `getUserMedia` 是否可能弹出授权框,权限状态未知时按可能弹窗处理 */
129
+ willPrompt: boolean;
130
+ /** 能力明细 */
131
+ capabilities: MicrophoneCapabilities;
132
+ }
133
+ /**
134
+ * 同步获取麦克风相关 API 的能力明细。
135
+ *
136
+ * @remarks
137
+ * 纯特性探测,不调用任何采集接口,**不会触发权限弹窗**,也没有异步开销。
138
+ *
139
+ * @returns 能力明细
140
+ *
141
+ * @example
142
+ * ```typescript
143
+ * const caps = getMicrophoneCapabilities();
144
+ * if (!caps.secureContext) {
145
+ * console.warn('请在 https 或 localhost 下使用对讲');
146
+ * }
147
+ * ```
148
+ *
149
+ * @since 2.0.8
150
+ */
151
+ export declare function getMicrophoneCapabilities(): MicrophoneCapabilities;
152
+ /**
153
+ * 同步判断当前环境是否具备采集麦克风的能力。
154
+ *
155
+ * @remarks
156
+ * 不会触发权限弹窗,也不查询权限与设备,因此没有异步开销,适合在渲染期做分支判断,
157
+ * 比如决定是否展示对讲按钮。需要知道具体原因或权限状态时使用
158
+ * {@link checkMicrophoneSupport}。
159
+ *
160
+ * 返回 `true` 只代表「可以去尝试」,不代表一定能拿到音频流:权限可能已被拒绝、
161
+ * 设备可能被其他应用占用、系统层面可能没有录音设备。
162
+ *
163
+ * @returns 具备采集能力时返回 `true`,否则返回 `false`
164
+ *
165
+ * @example
166
+ * ```typescript
167
+ * if (isMicrophoneSupported()) {
168
+ * renderTalkButton();
169
+ * }
170
+ * ```
171
+ *
172
+ * @since 2.0.8
173
+ */
174
+ export declare function isMicrophoneSupported(): boolean;
175
+ /**
176
+ * 检测麦克风支持情况,**不会触发权限弹窗**。
177
+ *
178
+ * @remarks
179
+ * 检测过程只做特性探测、`navigator.permissions.query()` 与
180
+ * `navigator.mediaDevices.enumerateDevices()`,这三类操作都不会向用户弹出授权框,
181
+ * 全程不调用 `getUserMedia`。
182
+ *
183
+ * 判定顺序为:运行环境 → 安全上下文 → Permissions Policy → `getUserMedia` 能力
184
+ * → 权限状态 → 设备存在性,命中即短路返回,能力层面不通过时不会发起任何异步探测。
185
+ *
186
+ * 已覆盖的兼容性差异:
187
+ *
188
+ * - **非安全上下文**:Chromium 在 `http` 下(`localhost` 除外)不挂载
189
+ * `navigator.mediaDevices`,单看 API 会误判为「浏览器不支持」,因此优先判安全上下文。
190
+ * `isSecureContext` 本身在 IE 与老版 Safari 不存在,已退化为协议与主机名判断
191
+ * - **权限查询**:Chromium 支持查询 `microphone`;Safari 全系与 Firefox 会抛
192
+ * `TypeError`,部分老版实现为同步抛错。两处均已兜住并降级为 `unknown`
193
+ * - **设备枚举**:未授权时 Chromium 返回 `label` 为空的占位项;Safari、开启
194
+ * `resistFingerprinting` 的 Firefox、Brave 等可能返回空数组。空数组判为 `unknown`
195
+ * 而非「没有麦克风」,避免误杀
196
+ * - **iframe**:未声明 `allow="microphone"` 时 `getUserMedia` 会以 `NotAllowedError`
197
+ * 失败。通过非标准的 `document.featurePolicy` / `document.permissionsPolicy` 探测,
198
+ * 仅 Chromium 可用,其他浏览器下跳过该项
199
+ * - **旧版内核**:单独上报 `legacyGetUserMedia`,覆盖只有前缀 API 的老版 Android 与 UC 内核
200
+ * - **iOS**:iOS 14.3 之前的 WKWebView(含微信等 App 内置浏览器)没有
201
+ * `getUserMedia`,由能力探测直接命中 `no-getusermedia`,无需 UA 判断
202
+ * - **WebView 卡死**:`enumerateDevices()` 在部分 Android WebView 下可能不 settle,已加超时保护
203
+ * - **非浏览器环境**:SSR 与 Web Worker 下不访问 `window`、`document`,返回
204
+ * `unsupported-environment`
205
+ *
206
+ * 由于权限与设备在部分浏览器下无法探知,`available` 为 `true` 仍可能在真正调用
207
+ * `getUserMedia` 时失败,调用处必须保留 `catch`。
208
+ *
209
+ * @param options - 检测配置
210
+ * @returns 检测结果,该 Promise 不会 reject
211
+ *
212
+ * @example
213
+ * ```typescript
214
+ * const result = await checkMicrophoneSupport();
215
+ *
216
+ * if (!result.available) {
217
+ * switch (result.reason) {
218
+ * case 'insecure-context':
219
+ * toast('请在 https 环境下使用对讲');
220
+ * break;
221
+ * case 'permissions-policy':
222
+ * toast('iframe 需要添加 allow="microphone"');
223
+ * break;
224
+ * case 'permission-denied':
225
+ * toast('麦克风权限已被拒绝,请在浏览器设置中开启');
226
+ * break;
227
+ * case 'no-device':
228
+ * toast('未检测到麦克风设备');
229
+ * break;
230
+ * default:
231
+ * toast('当前浏览器不支持语音对讲');
232
+ * }
233
+ * }
234
+ * ```
235
+ *
236
+ * @example
237
+ * ```typescript
238
+ * // 只做能力与权限检测, 跳过设备枚举
239
+ * const result = await checkMicrophoneSupport({ checkDevice: false, timeout: 1000 });
240
+ * result.willPrompt; // true 时点击对讲会弹授权框, 可先给用户一个说明
241
+ * ```
242
+ *
243
+ * @since 2.0.8
244
+ */
245
+ export declare function checkMicrophoneSupport(options?: CheckMicrophoneSupportOptions): Promise<MicrophoneSupportResult>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ezuikit/utils-tools",
3
- "version": "2.0.7",
3
+ "version": "2.0.9",
4
4
  "description": "tools utils",
5
5
  "main": "dist/index.js",
6
6
  "umd": "dist/index.umd.js",