@scrypted/prebuffer-mixin 0.1.64 → 0.1.65

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.
@@ -1,2 +1,2 @@
1
- !function(e,t){for(var r in t)e[r]=t[r]}(window,function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}([function(e,t,r){"use strict";var n=Object.create?function(e,t,r,n){void 0===n&&(n=r),Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]},i=function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||n(t,e,r)};Object.defineProperty(t,"__esModule",{value:!0}),t.MixinDeviceBase=t.ScryptedDeviceBase=void 0,i(r(2),t);const o=r(2);class s{constructor(e){this.nativeId=e}get storage(){return this._storage||(this._storage=deviceManager.getDeviceStorage(this.nativeId)),this._storage}get log(){return this._log||(this._log=deviceManager.getDeviceLogger(this.nativeId)),this._log}get console(){return this._console||(this._console=deviceManager.getDeviceConsole(this.nativeId)),this._console}_lazyLoadDeviceState(){this._deviceState||(this.nativeId?this._deviceState=deviceManager.getDeviceState(this.nativeId):this._deviceState=deviceManager.getDeviceState())}onDeviceEvent(e,t){return deviceManager.onDeviceEvent(this.nativeId,e,t)}}t.ScryptedDeviceBase=s;class a{constructor(e,t,r,n){this.mixinDevice=e,this.mixinDeviceInterfaces=t,this.mixinProviderNativeId=n,this._deviceState=r}get storage(){return this._storage||(this._storage=deviceManager.getMixinStorage(this.id,this.mixinProviderNativeId)),this._storage}get console(){return this._console||(deviceManager.getMixinConsole?this._console=deviceManager.getMixinConsole(this.id,this.mixinProviderNativeId):this._console=deviceManager.getDeviceConsole(this.mixinProviderNativeId)),this._console}onDeviceEvent(e,t){return deviceManager.onMixinEvent(this.id,this.mixinProviderNativeId,e,t)}_lazyLoadDeviceState(){}release(){}}t.MixinDeviceBase=a,function(){function e(e){return function(){return this._lazyLoadDeviceState(),this._deviceState[e]}}function t(e){return function(t){this._lazyLoadDeviceState(),this._deviceState[e]=t}}for(var r of Object.values(o.ScryptedInterfaceProperty))Object.defineProperty(s.prototype,r,{set:t(r),get:e(r)}),Object.defineProperty(a.prototype,r,{set:t(r),get:e(r)})}();let c={};try{c=Object.assign(c,{log:deviceManager.getDeviceLogger(void 0),deviceManager:deviceManager,endpointManager:endpointManager,mediaManager:mediaManager,systemManager:systemManager,pluginHostAPI:pluginHostAPI})}catch(e){console.error("sdk initialization error, import @scrypted/sdk/types instead",e)}t.default=c},function(e,t){e.exports=require("events")},function(e,t,r){"use strict";let n,i,o,s,a,c,d,u;Object.defineProperty(t,"__esModule",{value:!0}),t.ScryptedInterfaceDescriptors=t.ScryptedMimeTypes=t.ScryptedInterfaceProperty=t.ScryptedInterface=t.MediaPlayerState=t.LockState=t.ThermostatMode=t.TemperatureUnit=t.ScryptedDeviceType=void 0,t.ScryptedDeviceType=n,function(e){e.Builtin="Builtin",e.Camera="Camera",e.Fan="Fan",e.Light="Light",e.Switch="Switch",e.Outlet="Outlet",e.Sensor="Sensor",e.Scene="Scene",e.Program="Program",e.Automation="Automation",e.Vacuum="Vacuum",e.Notifier="Notifier",e.Thermostat="Thermostat",e.Lock="Lock",e.PasswordControl="PasswordControl",e.Display="Display",e.Speaker="Speaker",e.Event="Event",e.Entry="Entry",e.Garage="Garage",e.DeviceProvider="DeviceProvider",e.DataSource="DataSource",e.API="API",e.Doorbell="Doorbell",e.Irrigation="Irrigation",e.Valve="Valve",e.Person="Person",e.Unknown="Unknown"}(n||(t.ScryptedDeviceType=n={})),t.TemperatureUnit=i,function(e){e.C="C",e.F="F"}(i||(t.TemperatureUnit=i={})),t.ThermostatMode=o,function(e){e.Off="Off",e.Cool="Cool",e.Heat="Heat",e.HeatCool="HeatCool",e.Auto="Auto",e.FanOnly="FanOnly",e.Purifier="Purifier",e.Eco="Eco",e.Dry="Dry",e.On="On"}(o||(t.ThermostatMode=o={})),t.LockState=s,function(e){e.Locked="Locked",e.Unlocked="Unlocked",e.Jammed="Jammed"}(s||(t.LockState=s={})),t.MediaPlayerState=a,function(e){e.Idle="Idle",e.Playing="Playing",e.Paused="Paused",e.Buffering="Buffering"}(a||(t.MediaPlayerState=a={})),t.ScryptedInterface=c,function(e){e.ScryptedDevice="ScryptedDevice",e.OnOff="OnOff",e.Brightness="Brightness",e.ColorSettingTemperature="ColorSettingTemperature",e.ColorSettingRgb="ColorSettingRgb",e.ColorSettingHsv="ColorSettingHsv",e.Notifier="Notifier",e.StartStop="StartStop",e.Pause="Pause",e.Dock="Dock",e.TemperatureSetting="TemperatureSetting",e.Thermometer="Thermometer",e.HumiditySensor="HumiditySensor",e.Camera="Camera",e.VideoCamera="VideoCamera",e.Intercom="Intercom",e.Lock="Lock",e.PasswordStore="PasswordStore",e.Authenticator="Authenticator",e.Scene="Scene",e.Entry="Entry",e.EntrySensor="EntrySensor",e.DeviceProvider="DeviceProvider",e.Battery="Battery",e.Refresh="Refresh",e.MediaPlayer="MediaPlayer",e.Online="Online",e.SoftwareUpdate="SoftwareUpdate",e.BufferConverter="BufferConverter",e.Settings="Settings",e.BinarySensor="BinarySensor",e.IntrusionSensor="IntrusionSensor",e.PowerSensor="PowerSensor",e.AudioSensor="AudioSensor",e.MotionSensor="MotionSensor",e.OccupancySensor="OccupancySensor",e.FloodSensor="FloodSensor",e.UltravioletSensor="UltravioletSensor",e.LuminanceSensor="LuminanceSensor",e.PositionSensor="PositionSensor",e.MediaSource="MediaSource",e.MessagingEndpoint="MessagingEndpoint",e.OauthClient="OauthClient",e.MixinProvider="MixinProvider",e.HttpRequestHandler="HttpRequestHandler",e.EngineIOHandler="EngineIOHandler",e.PushHandler="PushHandler",e.Program="Program",e.Scriptable="Scriptable",e.ObjectDetector="ObjectDetector"}(c||(t.ScryptedInterface=c={})),t.ScryptedInterfaceProperty=d,function(e){e.id="id",e.interfaces="interfaces",e.mixins="mixins",e.info="info",e.name="name",e.providedInterfaces="providedInterfaces",e.providedName="providedName",e.providedRoom="providedRoom",e.providedType="providedType",e.providerId="providerId",e.room="room",e.type="type",e.on="on",e.brightness="brightness",e.colorTemperature="colorTemperature",e.rgb="rgb",e.hsv="hsv",e.running="running",e.paused="paused",e.docked="docked",e.thermostatAvailableModes="thermostatAvailableModes",e.thermostatMode="thermostatMode",e.thermostatSetpoint="thermostatSetpoint",e.thermostatSetpointHigh="thermostatSetpointHigh",e.thermostatSetpointLow="thermostatSetpointLow",e.temperature="temperature",e.temperatureUnit="temperatureUnit",e.humidity="humidity",e.lockState="lockState",e.entryOpen="entryOpen",e.batteryLevel="batteryLevel",e.online="online",e.updateAvailable="updateAvailable",e.fromMimeType="fromMimeType",e.toMimeType="toMimeType",e.binaryState="binaryState",e.intrusionDetected="intrusionDetected",e.powerDetected="powerDetected",e.motionDetected="motionDetected",e.audioDetected="audioDetected",e.occupied="occupied",e.flooded="flooded",e.ultraviolet="ultraviolet",e.luminance="luminance",e.position="position"}(d||(t.ScryptedInterfaceProperty=d={})),t.ScryptedMimeTypes=u,function(e){e.AcceptUrlParameter="accept-url",e.Url="text/x-uri",e.InsecureLocalUrl="text/x-insecure-local-uri",e.LocalUrl="text/x-local-uri",e.PushEndpoint="text/x-push-endpoint",e.FFmpegInput="x-scrypted/x-ffmpeg-input",e.RTCAVOffer="x-scrypted/x-rtc-av-offer",e.RTCAVAnswer="x-scrypted/x-rtc-av-answer"}(u||(t.ScryptedMimeTypes=u={}));t.ScryptedInterfaceDescriptors={ScryptedDevice:{name:"ScryptedDevice",properties:["id","interfaces","mixins","info","name","providedInterfaces","providedName","providedRoom","providedType","providerId","room","type"],methods:["listen","setName","setRoom","setType"]},OnOff:{name:"OnOff",properties:["on"],methods:["turnOff","turnOn"]},Brightness:{name:"Brightness",properties:["brightness"],methods:["setBrightness"]},ColorSettingTemperature:{name:"ColorSettingTemperature",properties:["colorTemperature"],methods:["getTemperatureMaxK","getTemperatureMinK","setColorTemperature"]},ColorSettingRgb:{name:"ColorSettingRgb",properties:["rgb"],methods:["setRgb"]},ColorSettingHsv:{name:"ColorSettingHsv",properties:["hsv"],methods:["setHsv"]},Notifier:{name:"Notifier",properties:[],methods:["sendNotification"]},StartStop:{name:"StartStop",properties:["running"],methods:["start","stop"]},Pause:{name:"Pause",properties:["paused"],methods:["pause","resume"]},Dock:{name:"Dock",properties:["docked"],methods:["dock"]},TemperatureSetting:{name:"TemperatureSetting",properties:["thermostatAvailableModes","thermostatMode","thermostatSetpoint","thermostatSetpointHigh","thermostatSetpointLow"],methods:["setThermostatMode","setThermostatSetpoint","setThermostatSetpointHigh","setThermostatSetpointLow"]},Thermometer:{name:"Thermometer",properties:["temperature","temperatureUnit"],methods:[]},HumiditySensor:{name:"HumiditySensor",properties:["humidity"],methods:[]},Camera:{name:"Camera",properties:[],methods:["takePicture"]},VideoCamera:{name:"VideoCamera",properties:[],methods:["getVideoStream","getVideoStreamOptions"]},Intercom:{name:"Intercom",properties:[],methods:["startIntercom","stopIntercom"]},Lock:{name:"Lock",properties:["lockState"],methods:["lock","unlock"]},PasswordStore:{name:"PasswordStore",properties:[],methods:["addPassword","getPasswords","removePassword"]},Authenticator:{name:"Authenticator",properties:[],methods:["checkPassword"]},Scene:{name:"Scene",properties:[],methods:["activate","deactivate","isReversible"]},Entry:{name:"Entry",properties:[],methods:["closeEntry","openEntry"]},EntrySensor:{name:"EntrySensor",properties:["entryOpen"],methods:[]},DeviceProvider:{name:"DeviceProvider",properties:[],methods:["discoverDevices","getDevice"]},Battery:{name:"Battery",properties:["batteryLevel"],methods:[]},Refresh:{name:"Refresh",properties:[],methods:["getRefreshFrequency","refresh"]},MediaPlayer:{name:"MediaPlayer",properties:[],methods:["getMediaStatus","load","seek","skipNext","skipPrevious"]},Online:{name:"Online",properties:["online"],methods:[]},SoftwareUpdate:{name:"SoftwareUpdate",properties:["updateAvailable"],methods:["checkForUpdate","installUpdate"]},BufferConverter:{name:"BufferConverter",properties:["fromMimeType","toMimeType"],methods:["convert"]},Settings:{name:"Settings",properties:[],methods:["getSettings","putSetting"]},BinarySensor:{name:"BinarySensor",properties:["binaryState"],methods:[]},IntrusionSensor:{name:"IntrusionSensor",properties:["intrusionDetected"],methods:[]},PowerSensor:{name:"PowerSensor",properties:["powerDetected"],methods:[]},AudioSensor:{name:"AudioSensor",properties:["audioDetected"],methods:[]},MotionSensor:{name:"MotionSensor",properties:["motionDetected"],methods:[]},OccupancySensor:{name:"OccupancySensor",properties:["occupied"],methods:[]},FloodSensor:{name:"FloodSensor",properties:["flooded"],methods:[]},UltravioletSensor:{name:"UltravioletSensor",properties:["ultraviolet"],methods:[]},LuminanceSensor:{name:"LuminanceSensor",properties:["luminance"],methods:[]},PositionSensor:{name:"PositionSensor",properties:["position"],methods:[]},MediaSource:{name:"MediaSource",properties:[],methods:["getMedia"]},MessagingEndpoint:{name:"MessagingEndpoint",properties:[],methods:[]},OauthClient:{name:"OauthClient",properties:[],methods:["getOauthUrl","onOauthCallback"]},MixinProvider:{name:"MixinProvider",properties:[],methods:["canMixin","getMixin","releaseMixin"]},HttpRequestHandler:{name:"HttpRequestHandler",properties:[],methods:["onRequest"]},EngineIOHandler:{name:"EngineIOHandler",properties:[],methods:["onConnection"]},PushHandler:{name:"PushHandler",properties:[],methods:["onPush"]},Program:{name:"Program",properties:[],methods:["run"]},Scriptable:{name:"Scriptable",properties:[],methods:["saveScript","loadScripts","eval"]},ObjectDetector:{name:"ObjectDetector",properties:[],methods:["getDetectionInput","getObjectTypes"]}}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=r(10);Object.keys(n).forEach((function(e){"default"!==e&&"__esModule"!==e&&(e in t&&t[e]===n[e]||Object.defineProperty(t,e,{enumerable:!0,get:function(){return n[e]}}))}))},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,i=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=p();if(t&&t.has(e))return t.get(e);var r={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var o=n?Object.getOwnPropertyDescriptor(e,i):null;o&&(o.get||o.set)?Object.defineProperty(r,i,o):r[i]=e[i]}r.default=e,t&&t.set(e,r);return r}(r(0)),o=(n=r(1))&&n.__esModule?n:{default:n},s=r(5),a=r(6),c=r(3),d=r(11),u=r(13);function p(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return p=function(){return e},e}function l(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}const{mediaManager:m,log:f,systemManager:h,deviceManager:g}=i.default,v=["aac","mp3","mp2","",void 0,null];class y{constructor(e,t,r){l(this,"prebuffers",{mp4:[],mpegts:[],s16le:[]}),l(this,"events",new o.default),l(this,"detectedIdrInterval",0),l(this,"prevIdr",0),l(this,"incompatibleDetected",!1),l(this,"allowImmediateRestart",!1),l(this,"AUDIO_CONFIGURATION","audioConfiguration-"+this.streamId),this.mixin=e,this.streamName=t,this.streamId=r,this.storage=e.storage,this.console=e.console,this.mixinDevice=e.mixinDevice}ensurePrebufferSession(){this.parserSessionPromise||this.mixin.released||(this.console.log("prebuffer session started",this.streamId),this.parserSessionPromise=this.startPrebufferSession())}getAudioConfig(){const e=this.storage.getItem(this.AUDIO_CONFIGURATION)||"",t=-1!==e.indexOf("PCM Audio"),r=-1!==e.indexOf("Other Audio")||!t&&this.incompatibleDetected;return{audioConfig:e,pcmAudio:t,reencodeAudio:r}}async getMixinSettings(){var e,t,r;const n=[],i=this.parserSession;let o=0,s=0;for(const e of this.prebuffers.mp4){s=s||e.time;for(const t of e.chunk.chunks)o+=t.byteLength}const a=Date.now()-s,c=Math.round(o/a*8),d=this.streamName?"Rebroadcast: "+this.streamName:"Rebroadcast";return n.push({title:"Audio Codec Transcoding",group:d,description:"Configuring your camera to output AAC, MP3, or MP2 is recommended. PCM/G711 cameras should set this to Reencode.",type:"string",key:this.AUDIO_CONFIGURATION,value:this.storage.getItem(this.AUDIO_CONFIGURATION)||"MPEG-TS/MP4 Compatible or No Audio (Copy)",choices:["MPEG-TS/MP4 Compatible or No Audio (Copy)","Other Audio (Transcode)","PCM Audio (Copy, !Experimental!)"]},{group:d,title:"Detected Resolution and Bitrate",readonly:!0,value:`${(null==i||null===(e=i.inputVideoResolution)||void 0===e?void 0:e[0])||"unknown"} @ ${c||"unknown"} Kb/s`,description:"Configuring your camera to 1920x1080 is recommended."},{group:d,title:"Detected Video/Audio Codecs",readonly:!0,value:((null==i||null===(t=i.inputVideoCodec)||void 0===t?void 0:t.toString())||"unknown")+"/"+((null==i||null===(r=i.inputAudioCodec)||void 0===r?void 0:r.toString())||"unknown"),description:"Configuring your camera to H264 video (2000Kb/s) and AAC/MP3/MP2 audio is recommended."},{group:d,title:"Detected Keyframe Interval",description:"Configuring your camera to 4 seconds is recommended (IDR = FPS * 4 seconds).",readonly:!0,value:((this.detectedIdrInterval||0)/1e3).toString()||"none"}),n}async startPrebufferSession(){var e,t;this.prebuffers.mp4=[],this.prebuffers.mpegts=[],this.prebuffers.s16le=[];const r=parseInt(this.storage.getItem("prebufferDuration"))||1e4,n=await(0,c.probeVideoCamera)(this.mixinDevice);let o;n.options&&(o=n.options.find(e=>e.id===this.streamId));const s=null==n||null===(e=n.options)||void 0===e||null===(t=e[0].audio)||void 0===t?void 0:t.codec;this.incompatibleDetected=this.incompatibleDetected||s&&!v.includes(s),this.incompatibleDetected&&this.console.warn("configure your camera to output aac, mp3, or mp2 audio. incompatibl audio codec detected",s);const u=JSON.parse((await m.convertMediaObjectToBuffer(await this.mixinDevice.getVideoStream(o),i.ScryptedMimeTypes.FFmpegInput)).toString()),{audioConfig:p,pcmAudio:l,reencodeAudio:h}=this.getAudioConfig();let g;g=n.noAudio||l?["-an"]:h?[]:["-acodec","copy"];const y=["-vcodec","copy"],S={console:this.console,parsers:{mp4:(0,d.createFragmentedMp4Parser)({vcodec:y,acodec:g}),mpegts:(0,d.createMpegTsParser)({vcodec:y,acodec:g})},parseOnly:!0};l&&(S.parsers.s16le=(0,d.createPCMParser)()),this.parsers=S.parsers;const b=await(0,a.startRebroadcastSession)(u,S);let M;this.parserSession=b;const P=()=>{clearTimeout(M),M=setTimeout(()=>{this.console.error("watchdog for mp4 parser timed out... killing ffmpeg session"),b.kill()},6e4)};b.events.on("mp4-data",P),b.events.once("killed",()=>{this.parserSessionPromise=void 0,b.events.removeListener("mp4-data",P),clearTimeout(M)}),P(),b.inputAudioCodec?v.includes(b.inputAudioCodec)||(this.console.error("Detected audio codec was not AAC.",b.inputAudioCodec),p||(f.a(`${this.mixin.name} is using ${b.inputAudioCodec} audio. Enable Reencode Audio in Rebroadcast Settings Audio Configuration to disable this alert.`),this.incompatibleDetected=!0,this.allowImmediateRestart=!0)):this.console.warn("no audio detected."),"h264"!==b.inputVideoCodec&&this.console.error("video codec is not h264. If there are errors, try changing your camera's encoder output.");for(const e of["mpegts","mp4","s16le"]){const t=e+"-data";let n=this.prebuffers[e],i=0;b.events.on(t,o=>{const s=Date.now();for("mdat"===o.type&&(this.prevIdr&&(this.detectedIdrInterval=s-this.prevIdr),this.prevIdr=s),n.push({time:s,chunk:o});n.length&&n[0].time<s-r;)n.shift(),i++;i>1e3&&(n=this.prebuffers[e]=n.slice(),i=0),this.events.emit(t,o)})}return b}async getVideoStream(e){var t,r;this.ensurePrebufferSession();const n=await this.parserSessionPromise,i="false"!==this.storage.getItem("sendKeyframe"),o=(null==e?void 0:e.prebuffer)||(i?1.5*Math.max(4e3,this.detectedIdrInterval||4e3):0);if(!(null!=e&&e.prebuffer||i)){return m.createFFmpegMediaObject(n.ffmpegInputs.mpegts)}this.console.log("prebuffer request started",this.streamId);const s=async e=>{const t=e+"-data",r=this.prebuffers[e],{server:i,port:s}=await(0,a.createRebroadcaster)({connect:(e,s)=>{i.close();const a=Date.now(),c=()=>{s(),this.console.log("prebuffer request ended"),this.events.removeListener(t,e),n.events.removeListener("killed",c)};this.events.on(t,e),n.events.once("killed",c);for(const t of r)t.time<a-o||e(t.chunk);return c}});return setTimeout(()=>i.close(),3e4),s},c=(null==e?void 0:e.container)||"mpegts",d=n.ffmpegInputs[c].mediaStreamOptions?Object.assign({},n.ffmpegInputs[c].mediaStreamOptions):{};d.prebuffer=o;const{audioConfig:u,pcmAudio:p,reencodeAudio:l}=this.getAudioConfig();l&&(d.audio={}),d.video&&null!==(t=n.inputVideoResolution)&&void 0!==t&&t[2]&&null!==(r=n.inputVideoResolution)&&void 0!==r&&r[3]&&Object.assign(d.video,{width:parseInt(n.inputVideoResolution[2]),height:parseInt(n.inputVideoResolution[3])});const f={inputArguments:["-f",c,"-i","tcp://127.0.0.1:"+await s(c)],mediaStreamOptions:d};p&&f.inputArguments.push("-f","s16le","-i","tcp://127.0.0.1:"+await s("s16le")),this.console.log("prebuffer ffmpeg input",f.inputArguments);return m.createFFmpegMediaObject(f)}}class S extends s.SettingsMixinDeviceBase{constructor(e,t,r,n){super(e,r,{providerNativeId:n,mixinDeviceInterfaces:t,group:"Prebuffer Settings",groupKey:"prebuffer"}),l(this,"released",!1),l(this,"sessions",new Map),this.delayStart()}delayStart(){this.console.log("prebuffer sessions starting in 5 seconds"),setTimeout(()=>this.ensurePrebufferSessions(),5e3)}async getVideoStream(e){await this.ensurePrebufferSessions();let t=null==e?void 0:e.id;if(!t&&!this.sessions.has(t)){var r;const n=await this.mixinDevice.getVideoStream(e),o=JSON.parse((await m.convertMediaObjectToBuffer(n,i.ScryptedMimeTypes.FFmpegInput)).toString());t=null==o||null===(r=o.mediaStreamOptions)||void 0===r?void 0:r.id,this.sessions.set(null==e?void 0:e.id,this.sessions.get(t))}let n=this.sessions.get(t);return n?(n.ensurePrebufferSession(),await n.parserSessionPromise,n=this.sessions.get(t),n?n.getVideoStream(e):this.mixinDevice.getVideoStream(e)):this.mixinDevice.getVideoStream(e)}async ensurePrebufferSessions(){const e=await this.mixinDevice.getVideoStreamOptions(),t=this.getEnabledMediaStreamOptions(e),r=t?t.map(e=>e.id):[void 0];for(const t of r){let r=this.sessions.get(t);if(!r){var n;const i=null===(n=e.find(e=>e.id===t))||void 0===n?void 0:n.name;r=new y(this,i,t),r.ensurePrebufferSession(),this.sessions.set(t,r)}}g.onMixinEvent(this.id,this.mixinProviderNativeId,i.ScryptedInterface.Settings,void 0)}async getMixinSettings(){const e=[],t=await this.mixinDevice.getVideoStreamOptions(),r=this.getEnabledMediaStreamOptions(t);r&&(null==t?void 0:t.length)>1&&e.push({title:"Prebuffered Streams",description:"The streams to prebuffer. Enable only as necessary to reduce traffic.",key:"enabledStreams",value:r.map(e=>e.name||""),choices:t.map(e=>e.name),multiple:!0}),e.push({title:"Prebuffer Duration",description:"Duration of the prebuffer in milliseconds.",type:"number",key:"prebufferDuration",value:this.storage.getItem("prebufferDuration")||1e4.toString()},{title:"Start at Previous Keyframe",description:"Start live streams from the previous key frame. Improves startup time.",type:"boolean",key:"sendKeyframe",value:("false"!==this.storage.getItem("sendKeyframe")).toString()});for(const t of new Set([...this.sessions.values()]))e.push(...await t.getMixinSettings());return e}async putMixinSetting(e,t){const r=this.sessions;this.sessions=new Map,"enabledStreams"===e?this.storage.setItem(e,JSON.stringify(t)):this.storage.setItem(e,t.toString());for(const e of r.values()){var n;null===(n=e.parserSessionPromise)||void 0===n||n.then(e=>e.kill())}this.ensurePrebufferSessions()}getEnabledMediaStreamOptions(e){if(e&&e.length){try{const t=JSON.parse(this.storage.getItem("enabledStreams"));return e.filter(e=>t.includes(e.name))}catch(e){}return[e[0]]}}async getVideoStreamOptions(){const e=await this.mixinDevice.getVideoStreamOptions()||[];let t=this.getEnabledMediaStreamOptions(e);const r=parseInt(this.storage.getItem("prebufferDuration"))||1e4;if(t)for(const e of t)e.prebuffer=r;else e.push({prebuffer:r});return e}release(){this.console.log("prebuffer releasing if started"),this.released=!0;for(const t of this.sessions.values()){var e;null===(e=t.parserSessionPromise)||void 0===e||e.then(e=>{this.console.log("prebuffer released"),e.kill()})}}}class b extends u.AutoenableMixinProvider{constructor(e){super(e);for(const e of Object.keys(h.getSystemState())){var t;const r=h.getDeviceById(e);null!==(t=r.mixins)&&void 0!==t&&t.includes(this.id)&&r.getVideoStreamOptions()}const r=function(){var e=new Date;return e.setHours(24),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0),e.getTime()-(new Date).getTime()}()+72e5;this.log.i(`Rebroadcaster scheduled for restart at 2AM: ${Math.round(r/1e3/60)} minutes`),setTimeout(()=>g.requestRestart(),r)}async canMixin(e,t){return t.includes(i.ScryptedInterface.VideoCamera)?[i.ScryptedInterface.VideoCamera,i.ScryptedInterface.Settings]:null}async getMixin(e,t,r){return this.setHasEnabledMixin(r.id),new S(e,t,r,this.nativeId)}async releaseMixin(e,t){t.release()}}var M=new b;t.default=M},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SettingsMixinDeviceBase=void 0;var n=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=i();if(t&&t.has(e))return t.get(e);var r={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var s=n?Object.getOwnPropertyDescriptor(e,o):null;s&&(s.get||s.set)?Object.defineProperty(r,o,s):r[o]=e[o]}r.default=e,t&&t.set(e,r);return r}(r(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}const{deviceManager:o}=n.default;class s extends n.MixinDeviceBase{constructor(e,t,r){super(e,r.mixinDeviceInterfaces,t,r.providerNativeId),this.settingsGroup=r.group,this.settingsGroupKey=r.groupKey}async getSettings(){const e=(this.mixinDeviceInterfaces.includes(n.ScryptedInterface.Settings)?await this.mixinDevice.getSettings():[])||[],t=await this.getMixinSettings();for(const e of t)e.group=e.group||this.settingsGroup,e.key=this.settingsGroupKey+":"+e.key;return e.push(...t),e}async putSetting(e,t){var r;const i=this.settingsGroupKey+":";if(null==e||!e.startsWith(i))return this.mixinDevice.putSetting(e,t);await this.putMixinSetting(e.substring(i.length),t),null===(r=o.onMixinEvent)||void 0===r||r.call(o,this.id,this.mixinProviderNativeId,n.ScryptedInterface.Settings,null)}}t.SettingsMixinDeviceBase=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.parseResolution=p,t.parseVideoCodec=m,t.parseAudioCodec=f,t.startRebroadcastSession=async function(e,t){let r,a=0,d=!0;const l=new s.EventEmitter,{console:g}=t;let v,y,S;function b(){d&&l.emit("killed"),d=!1,null==D||D.kill();for(const e of I)null==e||e.close()}function M(){t.timeout&&(clearTimeout(r),r=setTimeout(b,t.timeout))}M();const P={},O=e.inputArguments.slice(),I=[];let w;const x=new Promise(e=>w=e);for(const i of Object.keys(t.parsers)){const s=t.parsers[i],c=i+"-data";if(P[i]={mediaStreamOptions:e.mediaStreamOptions},!t.parseOnly){const{server:t,port:n}=await h({connect:(e,t)=>{a++,clearTimeout(r);const n=()=>{l.removeListener(c,e),l.removeListener("killed",t),a--,0===a&&M(),t()};return l.on(c,e),l.once("killed",n),n}});I.push(t),e.inputArguments=["-f",i,"-i","tcp://127.0.0.1:"+n]}const d=(0,n.createServer)(async e=>{d.close(),w(e);try{const n=i+"-data";for await(const i of s.parse(e,parseInt(null===(t=S)||void 0===t?void 0:t[2]),parseInt(null===(r=S)||void 0===r?void 0:r[3]))){var t,r;l.emit(n,i)}}catch(e){g.error("rebroadcast parse error",e),b()}});I.push(d);const u=await(0,o.listenZeroCluster)(d);O.push(...s.outputArguments,"tcp://127.0.0.1:"+u)}O.unshift("-hide_banner"),g.log(O);const D=i.default.spawn(await u.getFFmpegPath(),O);return(0,c.ffmpegLogInitialOutput)(g,D),D.on("exit",b),f(D).then(e=>v=e),m(D).then(e=>y=e),p(D).then(e=>S=e),await x,{inputAudioCodec:v,inputVideoCodec:y,inputVideoResolution:S,events:l,resetActivityTimer:M,isActive:()=>d,kill:b,servers:I,cp:D,ffmpegInputs:P}},t.createRebroadcaster=h;var n=r(7),i=d(r(8)),o=r(9),s=r(1),a=d(r(0)),c=r(3);function d(e){return e&&e.__esModule?e:{default:e}}const{mediaManager:u}=a.default;async function p(e){return new Promise(t=>{const r=n=>{const i=n.toString(),o=/(([0-9]{2,5})x([0-9]{2,5}))/.exec(i);o&&(e.stdout.removeListener("data",r),e.stderr.removeListener("data",r),t(o))};e.stdout.on("data",r),e.stderr.on("data",r)})}async function l(e,t){return new Promise(r=>{const n=i=>{const o=i.toString(),s=o.indexOf(t+": ");if(-1!==s){const i=o.substring(s+t.length+1).trim();let a=i.indexOf(" ");const c=i.indexOf(",");-1!==a&&c<a&&(a=c),-1!==a&&(e.stdout.removeListener("data",n),e.stderr.removeListener("data",n),r(i.substring(0,a)))}};e.stdout.on("data",n),e.stderr.on("data",n)})}async function m(e){return l(e,"Video")}async function f(e){return l(e,"Audio")}async function h(e){const t=(0,n.createServer)(t=>{let r=!0;const n=()=>{t.removeAllListeners(),t.destroy();const e=i;i=void 0,null==e||e()};let i=null==e?void 0:e.connect(e=>{r&&(r=!1,e.startStream&&t.write(e.startStream));for(const r of e.chunks)t.write(r)},n);t.on("end",n),t.on("close",n),t.on("error",n)});return{server:t,port:await(0,o.listenZeroCluster)(t)}}},function(e,t){e.exports=require("net")},function(e,t){e.exports=require("child_process")},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.listenZeroCluster=async function(e){for(;;){const t=1e4+Math.round(3e4*Math.random());e.listen(t);try{return await(0,n.once)(e,"listening"),e.address().port}catch(e){}}};var n=r(1)},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ffmpegLogInitialOutput=function(e,t,r){var i,o;function s(e){const i=o=>{const s=o.toString();for(const e of n)if(-1!==s.indexOf(e))return;if(!r&&(-1!==s.indexOf("frame=")||-1!==s.indexOf("size=")))return e(s),e("video/audio detected, discarding further input"),t.stdout.removeListener("data",i),void t.stderr.removeListener("data",i);e(s)};return i}null===(i=t.stdout)||void 0===i||i.on("data",s(e.log)),null===(o=t.stderr)||void 0===o||o.on("data",s(e.error)),t.on("exit",()=>e.log("ffmpeg exited"))},t.probeVideoCamera=async function(e){let t;try{t=await e.getVideoStreamOptions()||[]}catch(e){}const r=t&&t.length&&null===t[0].audio;return{options:t,noAudio:r}};const n=["decode_slice_header error","no frame!","non-existing PPS"]},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createPCMParser=function(){return{container:"s16le",outputArguments:["-vn","-acodec","pcm_s16le","-f","s16le"],parse:s(512),findSyncFrame:o}},t.createMpegTsParser=function(e){return{container:"mpegts",outputArguments:[...(null==e?void 0:e.vcodec)||[],...(null==e?void 0:e.acodec)||[],"-f","mpegts"],parse:s(188,e=>{if(71!=e[0])throw new Error("Invalid sync byte in mpeg-ts packet. Terminating stream.")}),findSyncFrame(e){for(let t=0;t<e.length;t++){const r=e[t];for(let n=0;n<r.chunks.length;n++){const i=r.chunks[n];let o=0;for(;o+188<i.length;){const r=i.subarray(o,o+188);if(256==((31&r[1])<<8|r[2])&&32&r[3]&&r[4]>0&&64&r[5])return e.slice(t);o+=188}}}return e}}},t.parseFragmentedMP4=a,t.createFragmentedMp4Parser=function(e){return{container:"mp4",outputArguments:[...(null==e?void 0:e.vcodec)||[],...(null==e?void 0:e.acodec)||[],"-movflags","frag_keyframe+empty_moov+default_base_moof","-f","mp4"],async*parse(e){const t=a(e);let r,n,i;for await(const e of t)r?n||(n=e):r=e,yield{startStream:i,chunks:[e.header,e.data],type:e.type},r&&n&&!i&&(i=Buffer.concat([r.header,r.data,n.header,n.data]))},findSyncFrame:o}},t.createRawVideoParser=function(e){let t;e=e||{};const{size:r,everyNFrames:n}=e;r&&(t=`scale=${r.width}:${r.height}`);n&&n>1&&(t?t+=",":t="",t+=`select=not(mod(n\\,${n}))`);return{container:"rawvideo",outputArguments:[...t?["-vf",t]:[],"-an","-vcodec","rawvideo","-pix_fmt","yuv420p","-f","rawvideo"],async*parse(e,t,n){if(!t||!n)throw new Error("error parsing rawvideo, unknown width and height");const o=(t=(null==r?void 0:r.width)||t)*(n=(null==r?void 0:r.height)||n)*1.5;for(;;){const r=await(0,i.readLength)(e,o);yield{chunks:[r],width:t,height:n}}},findSyncFrame:o}};var n=r(1),i=r(12);function o(e){return e}function s(e,t){return async function*(r){let i=[],o=0;for(;;){const s=r.read();if(!s){await(0,n.once)(r,"readable");continue}if(i.push(s),o+=s.length,o<e)continue;const a=Buffer.concat(i);null==t||t(a);const c=a.length%e,d=a.slice(0,a.length-c),u=a.slice(a.length-c);i=[u],o=u.length,yield{chunks:[d]}}}}async function*a(e){for(;;){const t=await(0,i.readLength)(e,8),r=t.readInt32BE(0)-8,n=t.slice(4).toString(),o=await(0,i.readLength)(e,r);yield{header:t,length:r,type:n,data:o}}}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.readLength=async function(e,t){if(!t)return Buffer.alloc(0);{const r=e.read(t);if(r)return r}return new Promise((r,n)=>{const i=()=>{const n=e.read(t);n&&(s(),r(n))},o=()=>{s(),n(new Error(`stream ended during read for minimum ${t} bytes`))},s=()=>{e.removeListener("readable",i),e.removeListener("end",o)};e.on("readable",i),e.on("end",o)})}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.AutoenableMixinProvider=void 0;var n=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=i();if(t&&t.has(e))return t.get(e);var r={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var s=n?Object.getOwnPropertyDescriptor(e,o):null;s&&(s.get||s.set)?Object.defineProperty(r,o,s):r[o]=e[o]}r.default=e,t&&t.set(e,r);return r}(r(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}const{systemManager:o}=n.default;class s extends n.ScryptedDeviceBase{constructor(e){var t,r,i;super(e),i={},(r="hasEnabledMixin")in(t=this)?Object.defineProperty(t,r,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[r]=i;try{this.hasEnabledMixin=JSON.parse(this.storage.getItem("hasEnabledMixin"))}catch(e){this.hasEnabledMixin={}}this.pluginsComponent=o.getComponent("plugins"),o.listen(async(e,t,r)=>{t.eventInterface!==n.ScryptedInterface.ScryptedDevice||t.property||this.maybeEnableMixin(e)});for(const e of Object.keys(o.getSystemState())){const t=o.getDeviceById(e);this.maybeEnableMixin(t)}}async maybeEnableMixin(e){var t;if(!e||null!==(t=e.mixins)&&void 0!==t&&t.includes(this.id))return;if(this.hasEnabledMixin[e.id])return;if(!await this.canMixin(e.type,e.interfaces))return;this.log.i("auto enabling mixin for "+e.name);const r=e.mixins||[];r.push(this.id);const n=await this.pluginsComponent;await n.setMixins(e.id,r)}setHasEnabledMixin(e){this.hasEnabledMixin[e]||(this.hasEnabledMixin[e]=!0,this.storage.setItem("hasEnabledMixin",JSON.stringify(this.hasEnabledMixin)))}}t.AutoenableMixinProvider=s}]));
1
+ !function(e,t){for(var r in t)e[r]=t[r]}(window,function(e){var t={};function r(n){if(t[n])return t[n].exports;var i=t[n]={i:n,l:!1,exports:{}};return e[n].call(i.exports,i,i.exports,r),i.l=!0,i.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var i in e)r.d(n,i,function(t){return e[t]}.bind(null,i));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=4)}([function(e,t,r){"use strict";var n=Object.create?function(e,t,r,n){void 0===n&&(n=r),Object.defineProperty(e,n,{enumerable:!0,get:function(){return t[r]}})}:function(e,t,r,n){void 0===n&&(n=r),e[n]=t[r]},i=function(e,t){for(var r in e)"default"===r||Object.prototype.hasOwnProperty.call(t,r)||n(t,e,r)};Object.defineProperty(t,"__esModule",{value:!0}),t.MixinDeviceBase=t.ScryptedDeviceBase=void 0,i(r(2),t);const o=r(2);class s{constructor(e){this.nativeId=e}get storage(){return this._storage||(this._storage=deviceManager.getDeviceStorage(this.nativeId)),this._storage}get log(){return this._log||(this._log=deviceManager.getDeviceLogger(this.nativeId)),this._log}get console(){return this._console||(this._console=deviceManager.getDeviceConsole(this.nativeId)),this._console}_lazyLoadDeviceState(){this._deviceState||(this.nativeId?this._deviceState=deviceManager.getDeviceState(this.nativeId):this._deviceState=deviceManager.getDeviceState())}onDeviceEvent(e,t){return deviceManager.onDeviceEvent(this.nativeId,e,t)}}t.ScryptedDeviceBase=s;class a{constructor(e,t,r,n){this.mixinDevice=e,this.mixinDeviceInterfaces=t,this.mixinProviderNativeId=n,this._deviceState=r}get storage(){return this._storage||(this._storage=deviceManager.getMixinStorage(this.id,this.mixinProviderNativeId)),this._storage}get console(){return this._console||(deviceManager.getMixinConsole?this._console=deviceManager.getMixinConsole(this.id,this.mixinProviderNativeId):this._console=deviceManager.getDeviceConsole(this.mixinProviderNativeId)),this._console}onDeviceEvent(e,t){return deviceManager.onMixinEvent(this.id,this.mixinProviderNativeId,e,t)}_lazyLoadDeviceState(){}release(){}}t.MixinDeviceBase=a,function(){function e(e){return function(){return this._lazyLoadDeviceState(),this._deviceState[e]}}function t(e){return function(t){this._lazyLoadDeviceState(),this._deviceState[e]=t}}for(var r of Object.values(o.ScryptedInterfaceProperty))Object.defineProperty(s.prototype,r,{set:t(r),get:e(r)}),Object.defineProperty(a.prototype,r,{set:t(r),get:e(r)})}();let c={};try{c=Object.assign(c,{log:deviceManager.getDeviceLogger(void 0),deviceManager:deviceManager,endpointManager:endpointManager,mediaManager:mediaManager,systemManager:systemManager,pluginHostAPI:pluginHostAPI})}catch(e){console.error("sdk initialization error, import @scrypted/sdk/types instead",e)}t.default=c},function(e,t){e.exports=require("events")},function(e,t,r){"use strict";let n,i,o,s,a,c,d,u;Object.defineProperty(t,"__esModule",{value:!0}),t.ScryptedInterfaceDescriptors=t.ScryptedMimeTypes=t.ScryptedInterfaceProperty=t.ScryptedInterface=t.MediaPlayerState=t.LockState=t.ThermostatMode=t.TemperatureUnit=t.ScryptedDeviceType=void 0,t.ScryptedDeviceType=n,function(e){e.Builtin="Builtin",e.Camera="Camera",e.Fan="Fan",e.Light="Light",e.Switch="Switch",e.Outlet="Outlet",e.Sensor="Sensor",e.Scene="Scene",e.Program="Program",e.Automation="Automation",e.Vacuum="Vacuum",e.Notifier="Notifier",e.Thermostat="Thermostat",e.Lock="Lock",e.PasswordControl="PasswordControl",e.Display="Display",e.Speaker="Speaker",e.Event="Event",e.Entry="Entry",e.Garage="Garage",e.DeviceProvider="DeviceProvider",e.DataSource="DataSource",e.API="API",e.Doorbell="Doorbell",e.Irrigation="Irrigation",e.Valve="Valve",e.Person="Person",e.Unknown="Unknown"}(n||(t.ScryptedDeviceType=n={})),t.TemperatureUnit=i,function(e){e.C="C",e.F="F"}(i||(t.TemperatureUnit=i={})),t.ThermostatMode=o,function(e){e.Off="Off",e.Cool="Cool",e.Heat="Heat",e.HeatCool="HeatCool",e.Auto="Auto",e.FanOnly="FanOnly",e.Purifier="Purifier",e.Eco="Eco",e.Dry="Dry",e.On="On"}(o||(t.ThermostatMode=o={})),t.LockState=s,function(e){e.Locked="Locked",e.Unlocked="Unlocked",e.Jammed="Jammed"}(s||(t.LockState=s={})),t.MediaPlayerState=a,function(e){e.Idle="Idle",e.Playing="Playing",e.Paused="Paused",e.Buffering="Buffering"}(a||(t.MediaPlayerState=a={})),t.ScryptedInterface=c,function(e){e.ScryptedDevice="ScryptedDevice",e.OnOff="OnOff",e.Brightness="Brightness",e.ColorSettingTemperature="ColorSettingTemperature",e.ColorSettingRgb="ColorSettingRgb",e.ColorSettingHsv="ColorSettingHsv",e.Notifier="Notifier",e.StartStop="StartStop",e.Pause="Pause",e.Dock="Dock",e.TemperatureSetting="TemperatureSetting",e.Thermometer="Thermometer",e.HumiditySensor="HumiditySensor",e.Camera="Camera",e.VideoCamera="VideoCamera",e.Intercom="Intercom",e.Lock="Lock",e.PasswordStore="PasswordStore",e.Authenticator="Authenticator",e.Scene="Scene",e.Entry="Entry",e.EntrySensor="EntrySensor",e.DeviceProvider="DeviceProvider",e.Battery="Battery",e.Refresh="Refresh",e.MediaPlayer="MediaPlayer",e.Online="Online",e.SoftwareUpdate="SoftwareUpdate",e.BufferConverter="BufferConverter",e.Settings="Settings",e.BinarySensor="BinarySensor",e.IntrusionSensor="IntrusionSensor",e.PowerSensor="PowerSensor",e.AudioSensor="AudioSensor",e.MotionSensor="MotionSensor",e.OccupancySensor="OccupancySensor",e.FloodSensor="FloodSensor",e.UltravioletSensor="UltravioletSensor",e.LuminanceSensor="LuminanceSensor",e.PositionSensor="PositionSensor",e.MediaSource="MediaSource",e.MessagingEndpoint="MessagingEndpoint",e.OauthClient="OauthClient",e.MixinProvider="MixinProvider",e.HttpRequestHandler="HttpRequestHandler",e.EngineIOHandler="EngineIOHandler",e.PushHandler="PushHandler",e.Program="Program",e.Scriptable="Scriptable",e.ObjectDetector="ObjectDetector"}(c||(t.ScryptedInterface=c={})),t.ScryptedInterfaceProperty=d,function(e){e.id="id",e.interfaces="interfaces",e.mixins="mixins",e.info="info",e.name="name",e.providedInterfaces="providedInterfaces",e.providedName="providedName",e.providedRoom="providedRoom",e.providedType="providedType",e.providerId="providerId",e.room="room",e.type="type",e.on="on",e.brightness="brightness",e.colorTemperature="colorTemperature",e.rgb="rgb",e.hsv="hsv",e.running="running",e.paused="paused",e.docked="docked",e.thermostatAvailableModes="thermostatAvailableModes",e.thermostatMode="thermostatMode",e.thermostatSetpoint="thermostatSetpoint",e.thermostatSetpointHigh="thermostatSetpointHigh",e.thermostatSetpointLow="thermostatSetpointLow",e.temperature="temperature",e.temperatureUnit="temperatureUnit",e.humidity="humidity",e.lockState="lockState",e.entryOpen="entryOpen",e.batteryLevel="batteryLevel",e.online="online",e.updateAvailable="updateAvailable",e.fromMimeType="fromMimeType",e.toMimeType="toMimeType",e.binaryState="binaryState",e.intrusionDetected="intrusionDetected",e.powerDetected="powerDetected",e.motionDetected="motionDetected",e.audioDetected="audioDetected",e.occupied="occupied",e.flooded="flooded",e.ultraviolet="ultraviolet",e.luminance="luminance",e.position="position"}(d||(t.ScryptedInterfaceProperty=d={})),t.ScryptedMimeTypes=u,function(e){e.AcceptUrlParameter="accept-url",e.Url="text/x-uri",e.InsecureLocalUrl="text/x-insecure-local-uri",e.LocalUrl="text/x-local-uri",e.PushEndpoint="text/x-push-endpoint",e.FFmpegInput="x-scrypted/x-ffmpeg-input",e.RTCAVOffer="x-scrypted/x-rtc-av-offer",e.RTCAVAnswer="x-scrypted/x-rtc-av-answer"}(u||(t.ScryptedMimeTypes=u={}));t.ScryptedInterfaceDescriptors={ScryptedDevice:{name:"ScryptedDevice",properties:["id","interfaces","mixins","info","name","providedInterfaces","providedName","providedRoom","providedType","providerId","room","type"],methods:["listen","setName","setRoom","setType"]},OnOff:{name:"OnOff",properties:["on"],methods:["turnOff","turnOn"]},Brightness:{name:"Brightness",properties:["brightness"],methods:["setBrightness"]},ColorSettingTemperature:{name:"ColorSettingTemperature",properties:["colorTemperature"],methods:["getTemperatureMaxK","getTemperatureMinK","setColorTemperature"]},ColorSettingRgb:{name:"ColorSettingRgb",properties:["rgb"],methods:["setRgb"]},ColorSettingHsv:{name:"ColorSettingHsv",properties:["hsv"],methods:["setHsv"]},Notifier:{name:"Notifier",properties:[],methods:["sendNotification"]},StartStop:{name:"StartStop",properties:["running"],methods:["start","stop"]},Pause:{name:"Pause",properties:["paused"],methods:["pause","resume"]},Dock:{name:"Dock",properties:["docked"],methods:["dock"]},TemperatureSetting:{name:"TemperatureSetting",properties:["thermostatAvailableModes","thermostatMode","thermostatSetpoint","thermostatSetpointHigh","thermostatSetpointLow"],methods:["setThermostatMode","setThermostatSetpoint","setThermostatSetpointHigh","setThermostatSetpointLow"]},Thermometer:{name:"Thermometer",properties:["temperature","temperatureUnit"],methods:[]},HumiditySensor:{name:"HumiditySensor",properties:["humidity"],methods:[]},Camera:{name:"Camera",properties:[],methods:["takePicture"]},VideoCamera:{name:"VideoCamera",properties:[],methods:["getVideoStream","getVideoStreamOptions"]},Intercom:{name:"Intercom",properties:[],methods:["startIntercom","stopIntercom"]},Lock:{name:"Lock",properties:["lockState"],methods:["lock","unlock"]},PasswordStore:{name:"PasswordStore",properties:[],methods:["addPassword","getPasswords","removePassword"]},Authenticator:{name:"Authenticator",properties:[],methods:["checkPassword"]},Scene:{name:"Scene",properties:[],methods:["activate","deactivate","isReversible"]},Entry:{name:"Entry",properties:[],methods:["closeEntry","openEntry"]},EntrySensor:{name:"EntrySensor",properties:["entryOpen"],methods:[]},DeviceProvider:{name:"DeviceProvider",properties:[],methods:["discoverDevices","getDevice"]},Battery:{name:"Battery",properties:["batteryLevel"],methods:[]},Refresh:{name:"Refresh",properties:[],methods:["getRefreshFrequency","refresh"]},MediaPlayer:{name:"MediaPlayer",properties:[],methods:["getMediaStatus","load","seek","skipNext","skipPrevious"]},Online:{name:"Online",properties:["online"],methods:[]},SoftwareUpdate:{name:"SoftwareUpdate",properties:["updateAvailable"],methods:["checkForUpdate","installUpdate"]},BufferConverter:{name:"BufferConverter",properties:["fromMimeType","toMimeType"],methods:["convert"]},Settings:{name:"Settings",properties:[],methods:["getSettings","putSetting"]},BinarySensor:{name:"BinarySensor",properties:["binaryState"],methods:[]},IntrusionSensor:{name:"IntrusionSensor",properties:["intrusionDetected"],methods:[]},PowerSensor:{name:"PowerSensor",properties:["powerDetected"],methods:[]},AudioSensor:{name:"AudioSensor",properties:["audioDetected"],methods:[]},MotionSensor:{name:"MotionSensor",properties:["motionDetected"],methods:[]},OccupancySensor:{name:"OccupancySensor",properties:["occupied"],methods:[]},FloodSensor:{name:"FloodSensor",properties:["flooded"],methods:[]},UltravioletSensor:{name:"UltravioletSensor",properties:["ultraviolet"],methods:[]},LuminanceSensor:{name:"LuminanceSensor",properties:["luminance"],methods:[]},PositionSensor:{name:"PositionSensor",properties:["position"],methods:[]},MediaSource:{name:"MediaSource",properties:[],methods:["getMedia"]},MessagingEndpoint:{name:"MessagingEndpoint",properties:[],methods:[]},OauthClient:{name:"OauthClient",properties:[],methods:["getOauthUrl","onOauthCallback"]},MixinProvider:{name:"MixinProvider",properties:[],methods:["canMixin","getMixin","releaseMixin"]},HttpRequestHandler:{name:"HttpRequestHandler",properties:[],methods:["onRequest"]},EngineIOHandler:{name:"EngineIOHandler",properties:[],methods:["onConnection"]},PushHandler:{name:"PushHandler",properties:[],methods:["onPush"]},Program:{name:"Program",properties:[],methods:["run"]},Scriptable:{name:"Scriptable",properties:[],methods:["saveScript","loadScripts","eval"]},ObjectDetector:{name:"ObjectDetector",properties:[],methods:["getDetectionInput","getObjectTypes"]}}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var n=r(10);Object.keys(n).forEach((function(e){"default"!==e&&"__esModule"!==e&&(e in t&&t[e]===n[e]||Object.defineProperty(t,e,{enumerable:!0,get:function(){return n[e]}}))}))},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=void 0;var n,i=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=p();if(t&&t.has(e))return t.get(e);var r={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var i in e)if(Object.prototype.hasOwnProperty.call(e,i)){var o=n?Object.getOwnPropertyDescriptor(e,i):null;o&&(o.get||o.set)?Object.defineProperty(r,i,o):r[i]=e[i]}r.default=e,t&&t.set(e,r);return r}(r(0)),o=(n=r(1))&&n.__esModule?n:{default:n},s=r(5),a=r(6),c=r(3),d=r(11),u=r(13);function p(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return p=function(){return e},e}function l(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}const{mediaManager:m,log:f,systemManager:h,deviceManager:g}=i.default,v=["aac","mp3","mp2","",void 0,null];class y{constructor(e,t,r){l(this,"prebuffers",{mp4:[],mpegts:[],s16le:[]}),l(this,"events",new o.default),l(this,"detectedIdrInterval",0),l(this,"prevIdr",0),l(this,"incompatibleDetected",!1),l(this,"allowImmediateRestart",!1),l(this,"AUDIO_CONFIGURATION","audioConfiguration-"+this.streamId),this.mixin=e,this.streamName=t,this.streamId=r,this.storage=e.storage,this.console=e.console,this.mixinDevice=e.mixinDevice}ensurePrebufferSession(){this.parserSessionPromise||this.mixin.released||(this.console.log("prebuffer session started",this.streamId),this.parserSessionPromise=this.startPrebufferSession())}getAudioConfig(){const e=this.storage.getItem(this.AUDIO_CONFIGURATION)||"",t=-1!==e.indexOf("PCM Audio"),r=-1!==e.indexOf("Other Audio")||!t&&this.incompatibleDetected;return{audioConfig:e,pcmAudio:t,reencodeAudio:r}}async getMixinSettings(){var e,t,r;const n=[],i=this.parserSession;let o=0,s=0;for(const e of this.prebuffers.mp4){s=s||e.time;for(const t of e.chunk.chunks)o+=t.byteLength}const a=Date.now()-s,c=Math.round(o/a*8),d=this.streamName?"Rebroadcast: "+this.streamName:"Rebroadcast";return n.push({title:"Audio Codec Transcoding",group:d,description:"Configuring your camera to output AAC, MP3, or MP2 is recommended. PCM/G711 cameras should set this to Reencode.",type:"string",key:this.AUDIO_CONFIGURATION,value:this.storage.getItem(this.AUDIO_CONFIGURATION)||"MPEG-TS/MP4 Compatible or No Audio (Copy)",choices:["MPEG-TS/MP4 Compatible or No Audio (Copy)","Other Audio (Transcode)","PCM Audio (Copy, !Experimental!)"]},{key:"detectedResolution",group:d,title:"Detected Resolution and Bitrate",readonly:!0,value:`${(null==i||null===(e=i.inputVideoResolution)||void 0===e?void 0:e[0])||"unknown"} @ ${c||"unknown"} Kb/s`,description:"Configuring your camera to 1920x1080 is recommended."},{key:"detectedCodec",group:d,title:"Detected Video/Audio Codecs",readonly:!0,value:((null==i||null===(t=i.inputVideoCodec)||void 0===t?void 0:t.toString())||"unknown")+"/"+((null==i||null===(r=i.inputAudioCodec)||void 0===r?void 0:r.toString())||"unknown"),description:"Configuring your camera to H264 video (2000Kb/s) and AAC/MP3/MP2 audio is recommended."},{key:"detectedKeyframe",group:d,title:"Detected Keyframe Interval",description:"Configuring your camera to 4 seconds is recommended (IDR = FPS * 4 seconds).",readonly:!0,value:((this.detectedIdrInterval||0)/1e3).toString()||"none"}),n}async startPrebufferSession(){var e,t;this.prebuffers.mp4=[],this.prebuffers.mpegts=[],this.prebuffers.s16le=[];const r=parseInt(this.storage.getItem("prebufferDuration"))||1e4,n=await(0,c.probeVideoCamera)(this.mixinDevice);let o;n.options&&(o=n.options.find(e=>e.id===this.streamId));const s=null==n||null===(e=n.options)||void 0===e||null===(t=e[0].audio)||void 0===t?void 0:t.codec;this.incompatibleDetected=this.incompatibleDetected||s&&!v.includes(s),this.incompatibleDetected&&this.console.warn("configure your camera to output aac, mp3, or mp2 audio. incompatibl audio codec detected",s);const u=JSON.parse((await m.convertMediaObjectToBuffer(await this.mixinDevice.getVideoStream(o),i.ScryptedMimeTypes.FFmpegInput)).toString()),{audioConfig:p,pcmAudio:l,reencodeAudio:h}=this.getAudioConfig();let g;g=n.noAudio||l?["-an"]:h?[]:["-acodec","copy"];const y=["-vcodec","copy"],S={console:this.console,parsers:{mp4:(0,d.createFragmentedMp4Parser)({vcodec:y,acodec:g}),mpegts:(0,d.createMpegTsParser)({vcodec:y,acodec:g})},parseOnly:!0};l&&(S.parsers.s16le=(0,d.createPCMParser)()),this.parsers=S.parsers;const b=await(0,a.startRebroadcastSession)(u,S);let M;this.parserSession=b;const P=()=>{clearTimeout(M),M=setTimeout(()=>{this.console.error("watchdog for mp4 parser timed out... killing ffmpeg session"),b.kill()},6e4)};b.events.on("mp4-data",P),b.events.once("killed",()=>{this.parserSessionPromise=void 0,b.events.removeListener("mp4-data",P),clearTimeout(M)}),P(),b.inputAudioCodec?v.includes(b.inputAudioCodec)||(this.console.error("Detected audio codec was not AAC.",b.inputAudioCodec),p||(f.a(`${this.mixin.name} is using ${b.inputAudioCodec} audio. Enable Reencode Audio in Rebroadcast Settings Audio Configuration to disable this alert.`),this.incompatibleDetected=!0,this.allowImmediateRestart=!0)):this.console.warn("no audio detected."),"h264"!==b.inputVideoCodec&&this.console.error("video codec is not h264. If there are errors, try changing your camera's encoder output.");for(const e of["mpegts","mp4","s16le"]){const t=e+"-data";let n=this.prebuffers[e],i=0;b.events.on(t,o=>{const s=Date.now();for("mdat"===o.type&&(this.prevIdr&&(this.detectedIdrInterval=s-this.prevIdr),this.prevIdr=s),n.push({time:s,chunk:o});n.length&&n[0].time<s-r;)n.shift(),i++;i>1e3&&(n=this.prebuffers[e]=n.slice(),i=0),this.events.emit(t,o)})}return b}async getVideoStream(e){var t,r;this.ensurePrebufferSession();const n=await this.parserSessionPromise,i="false"!==this.storage.getItem("sendKeyframe"),o=(null==e?void 0:e.prebuffer)||(i?1.5*Math.max(4e3,this.detectedIdrInterval||4e3):0);if(!(null!=e&&e.prebuffer||i)){return m.createFFmpegMediaObject(n.ffmpegInputs.mpegts)}this.console.log("prebuffer request started",this.streamId);const s=async e=>{const t=e+"-data",r=this.prebuffers[e],{server:i,port:s}=await(0,a.createRebroadcaster)({connect:(e,s)=>{i.close();const a=Date.now(),c=()=>{s(),this.console.log("prebuffer request ended"),this.events.removeListener(t,e),n.events.removeListener("killed",c)};this.events.on(t,e),n.events.once("killed",c);for(const t of r)t.time<a-o||e(t.chunk);return c}});return setTimeout(()=>i.close(),3e4),s},c=(null==e?void 0:e.container)||"mpegts",d=n.ffmpegInputs[c].mediaStreamOptions?Object.assign({},n.ffmpegInputs[c].mediaStreamOptions):{};d.prebuffer=o;const{audioConfig:u,pcmAudio:p,reencodeAudio:l}=this.getAudioConfig();l&&(d.audio={}),d.video&&null!==(t=n.inputVideoResolution)&&void 0!==t&&t[2]&&null!==(r=n.inputVideoResolution)&&void 0!==r&&r[3]&&Object.assign(d.video,{width:parseInt(n.inputVideoResolution[2]),height:parseInt(n.inputVideoResolution[3])});const f={inputArguments:["-f",c,"-i","tcp://127.0.0.1:"+await s(c)],mediaStreamOptions:d};p&&f.inputArguments.push("-f","s16le","-i","tcp://127.0.0.1:"+await s("s16le")),this.console.log("prebuffer ffmpeg input",f.inputArguments);return m.createFFmpegMediaObject(f)}}class S extends s.SettingsMixinDeviceBase{constructor(e,t,r,n){super(e,r,{providerNativeId:n,mixinDeviceInterfaces:t,group:"Prebuffer Settings",groupKey:"prebuffer"}),l(this,"released",!1),l(this,"sessions",new Map),this.delayStart()}delayStart(){this.console.log("prebuffer sessions starting in 5 seconds"),setTimeout(()=>this.ensurePrebufferSessions(),5e3)}async getVideoStream(e){await this.ensurePrebufferSessions();let t=null==e?void 0:e.id;if(!t&&!this.sessions.has(t)){var r;const n=await this.mixinDevice.getVideoStream(e),o=JSON.parse((await m.convertMediaObjectToBuffer(n,i.ScryptedMimeTypes.FFmpegInput)).toString());t=null==o||null===(r=o.mediaStreamOptions)||void 0===r?void 0:r.id,this.sessions.set(null==e?void 0:e.id,this.sessions.get(t))}let n=this.sessions.get(t);return n?(n.ensurePrebufferSession(),await n.parserSessionPromise,n=this.sessions.get(t),n?n.getVideoStream(e):this.mixinDevice.getVideoStream(e)):this.mixinDevice.getVideoStream(e)}async ensurePrebufferSessions(){const e=await this.mixinDevice.getVideoStreamOptions(),t=this.getEnabledMediaStreamOptions(e),r=t?t.map(e=>e.id):[void 0];for(const t of r){let r=this.sessions.get(t);if(!r){var n;const i=null===(n=e.find(e=>e.id===t))||void 0===n?void 0:n.name;r=new y(this,i,t),r.ensurePrebufferSession(),this.sessions.set(t,r)}}g.onMixinEvent(this.id,this.mixinProviderNativeId,i.ScryptedInterface.Settings,void 0)}async getMixinSettings(){const e=[],t=await this.mixinDevice.getVideoStreamOptions(),r=this.getEnabledMediaStreamOptions(t);r&&(null==t?void 0:t.length)>1&&e.push({title:"Prebuffered Streams",description:"The streams to prebuffer. Enable only as necessary to reduce traffic.",key:"enabledStreams",value:r.map(e=>e.name||""),choices:t.map(e=>e.name),multiple:!0}),e.push({title:"Prebuffer Duration",description:"Duration of the prebuffer in milliseconds.",type:"number",key:"prebufferDuration",value:this.storage.getItem("prebufferDuration")||1e4.toString()},{title:"Start at Previous Keyframe",description:"Start live streams from the previous key frame. Improves startup time.",type:"boolean",key:"sendKeyframe",value:("false"!==this.storage.getItem("sendKeyframe")).toString()});for(const t of new Set([...this.sessions.values()]))e.push(...await t.getMixinSettings());return e}async putMixinSetting(e,t){const r=this.sessions;this.sessions=new Map,"enabledStreams"===e?this.storage.setItem(e,JSON.stringify(t)):this.storage.setItem(e,t.toString());for(const e of r.values()){var n;null===(n=e.parserSessionPromise)||void 0===n||n.then(e=>e.kill())}this.ensurePrebufferSessions()}getEnabledMediaStreamOptions(e){if(e&&e.length){try{const t=JSON.parse(this.storage.getItem("enabledStreams"));return e.filter(e=>t.includes(e.name))}catch(e){}return[e[0]]}}async getVideoStreamOptions(){const e=await this.mixinDevice.getVideoStreamOptions()||[];let t=this.getEnabledMediaStreamOptions(e);const r=parseInt(this.storage.getItem("prebufferDuration"))||1e4;if(t)for(const e of t)e.prebuffer=r;else e.push({prebuffer:r});return e}release(){this.console.log("prebuffer releasing if started"),this.released=!0;for(const t of this.sessions.values()){var e;null===(e=t.parserSessionPromise)||void 0===e||e.then(e=>{this.console.log("prebuffer released"),e.kill()})}}}class b extends u.AutoenableMixinProvider{constructor(e){super(e);for(const e of Object.keys(h.getSystemState())){var t;const r=h.getDeviceById(e);null!==(t=r.mixins)&&void 0!==t&&t.includes(this.id)&&r.getVideoStreamOptions()}const r=function(){var e=new Date;return e.setHours(24),e.setMinutes(0),e.setSeconds(0),e.setMilliseconds(0),e.getTime()-(new Date).getTime()}()+72e5;this.log.i(`Rebroadcaster scheduled for restart at 2AM: ${Math.round(r/1e3/60)} minutes`),setTimeout(()=>g.requestRestart(),r)}async canMixin(e,t){return t.includes(i.ScryptedInterface.VideoCamera)?[i.ScryptedInterface.VideoCamera,i.ScryptedInterface.Settings]:null}async getMixin(e,t,r){return this.setHasEnabledMixin(r.id),new S(e,t,r,this.nativeId)}async releaseMixin(e,t){t.release()}}var M=new b;t.default=M},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.SettingsMixinDeviceBase=void 0;var n=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=i();if(t&&t.has(e))return t.get(e);var r={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var s=n?Object.getOwnPropertyDescriptor(e,o):null;s&&(s.get||s.set)?Object.defineProperty(r,o,s):r[o]=e[o]}r.default=e,t&&t.set(e,r);return r}(r(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}const{deviceManager:o}=n.default;class s extends n.MixinDeviceBase{constructor(e,t,r){super(e,r.mixinDeviceInterfaces,t,r.providerNativeId),this.settingsGroup=r.group,this.settingsGroupKey=r.groupKey}async getSettings(){const e=(this.mixinDeviceInterfaces.includes(n.ScryptedInterface.Settings)?await this.mixinDevice.getSettings():[])||[],t=await this.getMixinSettings();for(const e of t)e.group=e.group||this.settingsGroup,e.key=this.settingsGroupKey+":"+e.key;return e.push(...t),e}async putSetting(e,t){var r;const i=this.settingsGroupKey+":";if(null==e||!e.startsWith(i))return this.mixinDevice.putSetting(e,t);await this.putMixinSetting(e.substring(i.length),t),null===(r=o.onMixinEvent)||void 0===r||r.call(o,this.id,this.mixinProviderNativeId,n.ScryptedInterface.Settings,null)}}t.SettingsMixinDeviceBase=s},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.parseResolution=p,t.parseVideoCodec=m,t.parseAudioCodec=f,t.startRebroadcastSession=async function(e,t){let r,a=0,d=!0;const l=new s.EventEmitter,{console:g}=t;let v,y,S;function b(){d&&l.emit("killed"),d=!1,null==D||D.kill();for(const e of I)null==e||e.close()}function M(){t.timeout&&(clearTimeout(r),r=setTimeout(b,t.timeout))}M();const P={},O=e.inputArguments.slice(),I=[];let w;const x=new Promise(e=>w=e);for(const i of Object.keys(t.parsers)){const s=t.parsers[i],c=i+"-data";if(P[i]={mediaStreamOptions:e.mediaStreamOptions},!t.parseOnly){const{server:t,port:n}=await h({connect:(e,t)=>{a++,clearTimeout(r);const n=()=>{l.removeListener(c,e),l.removeListener("killed",t),a--,0===a&&M(),t()};return l.on(c,e),l.once("killed",n),n}});I.push(t),e.inputArguments=["-f",i,"-i","tcp://127.0.0.1:"+n]}const d=(0,n.createServer)(async e=>{d.close(),w(e);try{const n=i+"-data";for await(const i of s.parse(e,parseInt(null===(t=S)||void 0===t?void 0:t[2]),parseInt(null===(r=S)||void 0===r?void 0:r[3]))){var t,r;l.emit(n,i)}}catch(e){g.error("rebroadcast parse error",e),b()}});I.push(d);const u=await(0,o.listenZeroCluster)(d);O.push(...s.outputArguments,"tcp://127.0.0.1:"+u)}O.unshift("-hide_banner"),g.log(O);const D=i.default.spawn(await u.getFFmpegPath(),O);return(0,c.ffmpegLogInitialOutput)(g,D),D.on("exit",b),f(D).then(e=>v=e),m(D).then(e=>y=e),p(D).then(e=>S=e),await x,{inputAudioCodec:v,inputVideoCodec:y,inputVideoResolution:S,events:l,resetActivityTimer:M,isActive:()=>d,kill:b,servers:I,cp:D,ffmpegInputs:P}},t.createRebroadcaster=h;var n=r(7),i=d(r(8)),o=r(9),s=r(1),a=d(r(0)),c=r(3);function d(e){return e&&e.__esModule?e:{default:e}}const{mediaManager:u}=a.default;async function p(e){return new Promise(t=>{const r=n=>{const i=n.toString(),o=/(([0-9]{2,5})x([0-9]{2,5}))/.exec(i);o&&(e.stdout.removeListener("data",r),e.stderr.removeListener("data",r),t(o))};e.stdout.on("data",r),e.stderr.on("data",r)})}async function l(e,t){return new Promise(r=>{const n=i=>{const o=i.toString(),s=o.indexOf(t+": ");if(-1!==s){const i=o.substring(s+t.length+1).trim();let a=i.indexOf(" ");const c=i.indexOf(",");-1!==a&&c<a&&(a=c),-1!==a&&(e.stdout.removeListener("data",n),e.stderr.removeListener("data",n),r(i.substring(0,a)))}};e.stdout.on("data",n),e.stderr.on("data",n)})}async function m(e){return l(e,"Video")}async function f(e){return l(e,"Audio")}async function h(e){const t=(0,n.createServer)(t=>{let r=!0;const n=()=>{t.removeAllListeners(),t.destroy();const e=i;i=void 0,null==e||e()};let i=null==e?void 0:e.connect(e=>{r&&(r=!1,e.startStream&&t.write(e.startStream));for(const r of e.chunks)t.write(r)},n);t.on("end",n),t.on("close",n),t.on("error",n)});return{server:t,port:await(0,o.listenZeroCluster)(t)}}},function(e,t){e.exports=require("net")},function(e,t){e.exports=require("child_process")},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.listenZeroCluster=async function(e){for(;;){const t=1e4+Math.round(3e4*Math.random());e.listen(t);try{return await(0,n.once)(e,"listening"),e.address().port}catch(e){}}};var n=r(1)},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.ffmpegLogInitialOutput=function(e,t,r){var i,o;function s(e){const i=o=>{const s=o.toString();for(const e of n)if(-1!==s.indexOf(e))return;if(!r&&(-1!==s.indexOf("frame=")||-1!==s.indexOf("size=")))return e(s),e("video/audio detected, discarding further input"),t.stdout.removeListener("data",i),void t.stderr.removeListener("data",i);e(s)};return i}null===(i=t.stdout)||void 0===i||i.on("data",s(e.log)),null===(o=t.stderr)||void 0===o||o.on("data",s(e.error)),t.on("exit",()=>e.log("ffmpeg exited"))},t.probeVideoCamera=async function(e){let t;try{t=await e.getVideoStreamOptions()||[]}catch(e){}const r=t&&t.length&&null===t[0].audio;return{options:t,noAudio:r}};const n=["decode_slice_header error","no frame!","non-existing PPS"]},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.createPCMParser=function(){return{container:"s16le",outputArguments:["-vn","-acodec","pcm_s16le","-f","s16le"],parse:s(512),findSyncFrame:o}},t.createMpegTsParser=function(e){return{container:"mpegts",outputArguments:[...(null==e?void 0:e.vcodec)||[],...(null==e?void 0:e.acodec)||[],"-f","mpegts"],parse:s(188,e=>{if(71!=e[0])throw new Error("Invalid sync byte in mpeg-ts packet. Terminating stream.")}),findSyncFrame(e){for(let t=0;t<e.length;t++){const r=e[t];for(let n=0;n<r.chunks.length;n++){const i=r.chunks[n];let o=0;for(;o+188<i.length;){const r=i.subarray(o,o+188);if(256==((31&r[1])<<8|r[2])&&32&r[3]&&r[4]>0&&64&r[5])return e.slice(t);o+=188}}}return e}}},t.parseFragmentedMP4=a,t.createFragmentedMp4Parser=function(e){return{container:"mp4",outputArguments:[...(null==e?void 0:e.vcodec)||[],...(null==e?void 0:e.acodec)||[],"-movflags","frag_keyframe+empty_moov+default_base_moof","-f","mp4"],async*parse(e){const t=a(e);let r,n,i;for await(const e of t)r?n||(n=e):r=e,yield{startStream:i,chunks:[e.header,e.data],type:e.type},r&&n&&!i&&(i=Buffer.concat([r.header,r.data,n.header,n.data]))},findSyncFrame:o}},t.createRawVideoParser=function(e){let t;e=e||{};const{size:r,everyNFrames:n}=e;r&&(t=`scale=${r.width}:${r.height}`);n&&n>1&&(t?t+=",":t="",t+=`select=not(mod(n\\,${n}))`);return{container:"rawvideo",outputArguments:[...t?["-vf",t]:[],"-an","-vcodec","rawvideo","-pix_fmt","yuv420p","-f","rawvideo"],async*parse(e,t,n){if(!t||!n)throw new Error("error parsing rawvideo, unknown width and height");const o=(t=(null==r?void 0:r.width)||t)*(n=(null==r?void 0:r.height)||n)*1.5;for(;;){const r=await(0,i.readLength)(e,o);yield{chunks:[r],width:t,height:n}}},findSyncFrame:o}};var n=r(1),i=r(12);function o(e){return e}function s(e,t){return async function*(r){let i=[],o=0;for(;;){const s=r.read();if(!s){await(0,n.once)(r,"readable");continue}if(i.push(s),o+=s.length,o<e)continue;const a=Buffer.concat(i);null==t||t(a);const c=a.length%e,d=a.slice(0,a.length-c),u=a.slice(a.length-c);i=[u],o=u.length,yield{chunks:[d]}}}}async function*a(e){for(;;){const t=await(0,i.readLength)(e,8),r=t.readInt32BE(0)-8,n=t.slice(4).toString(),o=await(0,i.readLength)(e,r);yield{header:t,length:r,type:n,data:o}}}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.readLength=async function(e,t){if(!t)return Buffer.alloc(0);{const r=e.read(t);if(r)return r}return new Promise((r,n)=>{const i=()=>{const n=e.read(t);n&&(s(),r(n))},o=()=>{s(),n(new Error(`stream ended during read for minimum ${t} bytes`))},s=()=>{e.removeListener("readable",i),e.removeListener("end",o)};e.on("readable",i),e.on("end",o)})}},function(e,t,r){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.AutoenableMixinProvider=void 0;var n=function(e){if(e&&e.__esModule)return e;if(null===e||"object"!=typeof e&&"function"!=typeof e)return{default:e};var t=i();if(t&&t.has(e))return t.get(e);var r={},n=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var o in e)if(Object.prototype.hasOwnProperty.call(e,o)){var s=n?Object.getOwnPropertyDescriptor(e,o):null;s&&(s.get||s.set)?Object.defineProperty(r,o,s):r[o]=e[o]}r.default=e,t&&t.set(e,r);return r}(r(0));function i(){if("function"!=typeof WeakMap)return null;var e=new WeakMap;return i=function(){return e},e}const{systemManager:o}=n.default;class s extends n.ScryptedDeviceBase{constructor(e){var t,r,i;super(e),i={},(r="hasEnabledMixin")in(t=this)?Object.defineProperty(t,r,{value:i,enumerable:!0,configurable:!0,writable:!0}):t[r]=i;try{this.hasEnabledMixin=JSON.parse(this.storage.getItem("hasEnabledMixin"))}catch(e){this.hasEnabledMixin={}}this.pluginsComponent=o.getComponent("plugins"),o.listen(async(e,t,r)=>{t.eventInterface!==n.ScryptedInterface.ScryptedDevice||t.property||this.maybeEnableMixin(e)});for(const e of Object.keys(o.getSystemState())){const t=o.getDeviceById(e);this.maybeEnableMixin(t)}}async maybeEnableMixin(e){var t;if(!e||null!==(t=e.mixins)&&void 0!==t&&t.includes(this.id))return;if(this.hasEnabledMixin[e.id])return;if(!await this.canMixin(e.type,e.interfaces))return;this.log.i("auto enabling mixin for "+e.name);const r=e.mixins||[];r.push(this.id);const n=await this.pluginsComponent;await n.setMixins(e.id,r)}setHasEnabledMixin(e){this.hasEnabledMixin[e]||(this.hasEnabledMixin[e]=!0,this.storage.setItem("hasEnabledMixin",JSON.stringify(this.hasEnabledMixin)))}}t.AutoenableMixinProvider=s}]));
2
2
  //# sourceMappingURL=main.nodejs.js.map
package/dist/plugin.zip CHANGED
Binary file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@scrypted/prebuffer-mixin",
3
- "version": "0.1.64",
3
+ "version": "0.1.65",
4
4
  "description": "Rebroadcast and Prebuffer for VideoCameras.",
5
5
  "author": "Scrypted",
6
6
  "license": "Apache-2.0",
package/src/main.ts CHANGED
@@ -118,6 +118,7 @@ class PrebufferSession {
118
118
  ],
119
119
  },
120
120
  {
121
+ key: 'detectedResolution',
121
122
  group,
122
123
  title: 'Detected Resolution and Bitrate',
123
124
  readonly: true,
@@ -125,6 +126,7 @@ class PrebufferSession {
125
126
  description: 'Configuring your camera to 1920x1080 is recommended.',
126
127
  },
127
128
  {
129
+ key: 'detectedCodec',
128
130
  group,
129
131
  title: 'Detected Video/Audio Codecs',
130
132
  readonly: true,
@@ -132,6 +134,7 @@ class PrebufferSession {
132
134
  description: 'Configuring your camera to H264 video (2000Kb/s) and AAC/MP3/MP2 audio is recommended.'
133
135
  },
134
136
  {
137
+ key: 'detectedKeyframe',
135
138
  group,
136
139
  title: 'Detected Keyframe Interval',
137
140
  description: "Configuring your camera to 4 seconds is recommended (IDR = FPS * 4 seconds).",