@camera.ui/server 2.1.2 → 2.1.4

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.
Files changed (552) hide show
  1. package/dist/interface/assets/{404-pb2fRn1r.js → 404-6v3-U7nj.js} +1 -1
  2. package/dist/interface/assets/{About-eljMnDub.js → About-IMZSnCy7.js} +1 -1
  3. package/dist/interface/assets/{Adminpanel-BtQdiyre.js → Adminpanel-jq9sK1Ey.js} +1 -1
  4. package/dist/interface/assets/{Automation-DOiLJcU_.js → Automation-xs_GEpGx.js} +3 -3
  5. package/dist/interface/assets/{AutomationImport-DflZNRBB.js → AutomationImport-CR4fWWkU.js} +2 -2
  6. package/dist/interface/assets/{AutomationStore-qF_NTNUf.js → AutomationStore-rB-eVXdY.js} +2 -2
  7. package/dist/interface/assets/{AutomationStoreDetail-CUw-jBBR.js → AutomationStoreDetail-DzMg8IOO.js} +2 -2
  8. package/dist/interface/assets/Automations-DWI8Q2TS.js +2 -0
  9. package/dist/interface/assets/Camera-BIppnvyN.js +2 -0
  10. package/dist/interface/assets/Camera-BfMZmurS.css +1 -0
  11. package/dist/interface/assets/{CameraConsole-CEARcJYc.js → CameraConsole-CQLrlDvb.js} +2 -2
  12. package/dist/interface/assets/{Cameras-C0oHuoTR.js → Cameras-kIN6bWi1.js} +2 -2
  13. package/dist/interface/assets/Camview-4jdGGny8.js +1 -0
  14. package/dist/interface/assets/Camview-UCj_OW0s.css +1 -0
  15. package/dist/interface/assets/Config-DxYeS7cY.js +2 -0
  16. package/dist/interface/assets/{ConfigActionCameraControl-De0qb88r.js → ConfigActionCameraControl-Biu5BwNu.js} +1 -1
  17. package/dist/interface/assets/{ConfigActionDelay-nDK4i-AL.js → ConfigActionDelay-CK5j4XLw.js} +1 -1
  18. package/dist/interface/assets/{ConfigActionHttp-DX-vapgv.js → ConfigActionHttp-Dtvi3jZB.js} +1 -1
  19. package/dist/interface/assets/{ConfigActionImageInput-CS7U7BsI.js → ConfigActionImageInput-Dh0A20j9.js} +1 -1
  20. package/dist/interface/assets/{ConfigActionMqtt-82swCx_F.js → ConfigActionMqtt-DwZdnDlb.js} +1 -1
  21. package/dist/interface/assets/{ConfigActionNotification-t-1zN_1y.js → ConfigActionNotification-BVqYxGu8.js} +1 -1
  22. package/dist/interface/assets/{ConfigActionNotificationControl-jz3ez2Uq.js → ConfigActionNotificationControl-BTdnQqox.js} +1 -1
  23. package/dist/interface/assets/{ConfigActionOutput-B6uJheX1.js → ConfigActionOutput-Dv745ppL.js} +1 -1
  24. package/dist/interface/assets/{ConfigActionPlugin-LyOIrZnv.js → ConfigActionPlugin-C9QdPDXC.js} +1 -1
  25. package/dist/interface/assets/{ConfigActionSensor-BTqc1inw.js → ConfigActionSensor-D17wASao.js} +1 -1
  26. package/dist/interface/assets/{ConfigActionSnapshot-DdPy_Ubu.js → ConfigActionSnapshot-CrbMLwuh.js} +1 -1
  27. package/dist/interface/assets/{ConfigActionVariable-Csf7jPOm.js → ConfigActionVariable-C0HobSMN.js} +1 -1
  28. package/dist/interface/assets/{ConfigConditionIfElse-BvzwZ70p.js → ConfigConditionIfElse-DsedkGhY.js} +1 -1
  29. package/dist/interface/assets/ConfigConditionSensorState-rRLbA2_b.js +1 -0
  30. package/dist/interface/assets/{ConfigConditionSwitch-DJU2JC-3.js → ConfigConditionSwitch-5nEVS-Oj.js} +1 -1
  31. package/dist/interface/assets/{ConfigConditionTime-BxE2CJMA.js → ConfigConditionTime-CieLn-sp.js} +1 -1
  32. package/dist/interface/assets/ConfigSensorValueInput-CRRM_aBz.js +1 -0
  33. package/dist/interface/assets/{ConfigTriggerDetection-DpC8V8K8.js → ConfigTriggerDetection-CMVgejZ3.js} +1 -1
  34. package/dist/interface/assets/{ConfigTriggerGeofence-DTzax7bc.js → ConfigTriggerGeofence-cMhyndiz.js} +1 -1
  35. package/dist/interface/assets/{ConfigTriggerManual-CtjnnQb1.js → ConfigTriggerManual-Bd9H0AfP.js} +1 -1
  36. package/dist/interface/assets/{ConfigTriggerMqtt-C7J22EMe.js → ConfigTriggerMqtt-BIv5Ca91.js} +1 -1
  37. package/dist/interface/assets/{ConfigTriggerSchedule-DnYDDz3F.js → ConfigTriggerSchedule-CzWWcnFW.js} +1 -1
  38. package/dist/interface/assets/ConfigTriggerSensor-C5lsyxsh.js +1 -0
  39. package/dist/interface/assets/{ConfigTriggerSystem-D1JulYVd.js → ConfigTriggerSystem-WipCRwTJ.js} +1 -1
  40. package/dist/interface/assets/{ConfigTriggerWebhook-BrKFtq7o.js → ConfigTriggerWebhook-Bl0O4RBX.js} +1 -1
  41. package/dist/interface/assets/Console-GtK0GVLX.js +1 -0
  42. package/dist/interface/assets/CuiAutomationRunsDialog-CUPBuq_J.js +1 -0
  43. package/dist/interface/assets/CuiBottomSheet-DQNpk0mh.js +1 -0
  44. package/dist/interface/assets/{CuiBottomSheet-C_1_moNo.js → CuiBottomSheet-K19nZQiG.js} +1 -1
  45. package/dist/interface/assets/CuiCameraPipCard-e3_uYELi.js +1 -0
  46. package/dist/interface/assets/CuiCameraRecordings-CPAMltfx.js +1 -0
  47. package/dist/interface/assets/CuiCameraRecordings-fB3X6kad.css +1 -0
  48. package/dist/interface/assets/{CuiCameraShares-XwN5kuC7.js → CuiCameraShares-BTn5ys6X.js} +1 -1
  49. package/dist/interface/assets/{CuiCameraTable-BeeHLaiQ.js → CuiCameraTable-DYvQ-GCz.js} +2 -2
  50. package/dist/interface/assets/{CuiConsole-B7R7U9UZ.js → CuiConsole-C4PawCou.js} +2 -2
  51. package/dist/interface/assets/{CuiDataTable-CQhCu0px.js → CuiDataTable-CORQOWsf.js} +1 -1
  52. package/dist/interface/assets/CuiLightControl-BYkQ8Ue3.js +1 -0
  53. package/dist/interface/assets/CuiList-BgZBIhXP.js +1 -0
  54. package/dist/interface/assets/CuiMarkdownContent-CCdOW_TM.js +1 -0
  55. package/dist/interface/assets/CuiMarkdownContent-ChezqgI1.js +1 -0
  56. package/dist/interface/assets/{CuiPluginCard-rkhmuumi.css → CuiPluginCard-C3ANAXSI.css} +1 -1
  57. package/dist/interface/assets/CuiPluginCard-C91rKOge.js +2 -0
  58. package/dist/interface/assets/{CuiPluginCategoryChip-JkdbQU4X.js → CuiPluginCategoryChip-B_Zy4B42.js} +1 -1
  59. package/dist/interface/assets/{CuiPluginOAuthButton-LYMFfb3v.js → CuiPluginOAuthButton-IXGedGWs.js} +2 -2
  60. package/dist/interface/assets/{CuiPluginTrustBadge-sZF0UKMD.js → CuiPluginTrustBadge-DTfM8Jjo.js} +1 -1
  61. package/dist/interface/assets/{CuiQRCode-B4ysluWR.js → CuiQRCode-D5vwhyuQ.js} +1 -1
  62. package/dist/interface/assets/CuiRecordingsGrid-Sv3uyj9a.css +1 -0
  63. package/dist/interface/assets/CuiRecordingsGrid-yXEzhnc4.js +1 -0
  64. package/dist/interface/assets/CuiSchema-hK_tgUP9.js +1 -0
  65. package/dist/interface/assets/{CuiTopNavbarItem-rMsWME9B.js → CuiTopNavbarItem-DWLnn7Kh.js} +1 -1
  66. package/dist/interface/assets/Faces-DzwTi8P1.js +1 -0
  67. package/dist/interface/assets/FirstSteps-0ojmFGSr.js +1 -0
  68. package/dist/interface/assets/Instances-DvoFBGMx.js +1 -0
  69. package/dist/interface/assets/{Logs-8onUmCYX.js → Logs-Cii4oP8R.js} +2 -2
  70. package/dist/interface/assets/Menu-pvtuFKFM.js +1 -0
  71. package/dist/interface/assets/OAuthDeviceFlow-BZgtsIjF.js +1 -0
  72. package/dist/interface/assets/Plugin-BDqNeTCT.css +1 -0
  73. package/dist/interface/assets/Plugin-BKqpBWJy.js +1 -0
  74. package/dist/interface/assets/{PluginConsole-JFcH_ZW0.js → PluginConsole-BFsCogtB.js} +1 -1
  75. package/dist/interface/assets/PluginDetail-Dl0OM6me.js +2 -0
  76. package/dist/interface/assets/{PluginSchema-Gfn_csMP.js → PluginSchema-D45zblVz.js} +1 -1
  77. package/dist/interface/assets/PluginSearch-DdIcv9xA.js +1 -0
  78. package/dist/interface/assets/{PluginSearch-CLjLT9JT.css → PluginSearch-Dlzc-aJ3.css} +1 -1
  79. package/dist/interface/assets/PluginSearch-DxoQUW8M.js +2 -0
  80. package/dist/interface/assets/{PluginUpdateProgress-DaI9bwSV.js → PluginUpdateProgress-CsRGGH8J.js} +1 -1
  81. package/dist/interface/assets/Plugins-CGj8DSLJ.js +1 -0
  82. package/dist/interface/assets/Recordings-PojBH8L3.js +1 -0
  83. package/dist/interface/assets/SensorEdit-D2ChsNDL.js +1 -0
  84. package/dist/interface/assets/{SensorHistory-2TmYLaL4.js → SensorHistory-B6ZKgot4.js} +1 -1
  85. package/dist/interface/assets/Sensors-B-Qhfr5i.css +1 -0
  86. package/dist/interface/assets/Sensors-DyqWcB-G.js +2 -0
  87. package/dist/interface/assets/{Settings-8yG5ny5r.js → Settings-BFJO08mq.js} +1 -1
  88. package/dist/interface/assets/SettingsAccount-DREZwvce.js +1 -0
  89. package/dist/interface/assets/SettingsAccount-QxmP0dzI.js +1 -0
  90. package/dist/interface/assets/SettingsAppearance-BejKI3_C.js +1 -0
  91. package/dist/interface/assets/{SettingsAppearance-WQtOksbk.js → SettingsAppearance-_zvMUQvn.js} +1 -1
  92. package/dist/interface/assets/SettingsBackup-8HCwVmDA.js +1 -0
  93. package/dist/interface/assets/SettingsList-B4H786Cc.js +1 -0
  94. package/dist/interface/assets/SettingsMqtt-D7ajm1JA.js +1 -0
  95. package/dist/interface/assets/{SettingsNotifications-BVGmt0eF.js → SettingsNotifications-fDDuqryh.js} +2 -2
  96. package/dist/interface/assets/{SettingsPermissions-BPqDIjVt.js → SettingsPermissions-DYirYf1Z.js} +1 -1
  97. package/dist/interface/assets/SettingsRecordings-4NxpAbu5.js +1 -0
  98. package/dist/interface/assets/SettingsRemote-DOQkaNzp.js +1 -0
  99. package/dist/interface/assets/SettingsSystem-CVWkw449.js +2 -0
  100. package/dist/interface/assets/{SettingsUsers-BtT17FNe.js → SettingsUsers-Dc6L7Lt2.js} +1 -1
  101. package/dist/interface/assets/Terminal-BgVnN-2g.js +4 -0
  102. package/dist/interface/assets/{VariableInput-CkXZ00Gc.js → VariableInput-ZYn-Phl4.js} +1 -1
  103. package/dist/interface/assets/{VariableSuggestions-BD1kOG5f.js → VariableSuggestions-BnzdQP6R.js} +1 -1
  104. package/dist/interface/assets/VersionsHandler-BvKvGOlF.js +7 -0
  105. package/dist/interface/assets/{VirtualSensorCreate-DcwJ_w-l.js → VirtualSensorCreate-Dk_YYzxR.js} +1 -1
  106. package/dist/interface/assets/Workers-CjEzGjy8.js +2 -0
  107. package/dist/interface/assets/{account-CY80SLLf.js → account-DuSFtIHf.js} +1 -1
  108. package/dist/interface/assets/{alert-circle-pDGfnZ4K.js → alert-circle-C2AU59aR.js} +1 -1
  109. package/dist/interface/assets/{alert-outline-CeoXcnQc.js → alert-outline-GrD7-zHq.js} +1 -1
  110. package/dist/interface/assets/{api-Mny5Elfn.js → api-36pS71R2.js} +1 -1
  111. package/dist/interface/assets/api-CDvtqu1L.css +2 -0
  112. package/dist/interface/assets/api-DTFsk1zB.js +2 -0
  113. package/dist/interface/assets/{arrow-left-D9jDhvK5.js → arrow-left-C1N6U6kZ.js} +1 -1
  114. package/dist/interface/assets/{arrow-right-outline-DF7tkKYk.js → arrow-right-outline-C24f5mwe.js} +1 -1
  115. package/dist/interface/assets/{auth-9_Jjlsh0.js → auth-DYoO8jpd.js} +1 -1
  116. package/dist/interface/assets/automations-BOvDlvvx.js +1 -0
  117. package/dist/interface/assets/{back-filled-DUUGErMw.js → back-filled-DcBDBvvP.js} +1 -1
  118. package/dist/interface/assets/{bell-ring-DV73JIre.js → bell-ring-DSX81yd4.js} +1 -1
  119. package/dist/interface/assets/cameras.schema-BvnUX82v.js +1 -0
  120. package/dist/interface/assets/{cctv-jy5ROx0o.js → cctv-BA5DvNlE.js} +1 -1
  121. package/dist/interface/assets/{check-circle-FwoylV5-.js → check-circle-Do_mBN_A.js} +1 -1
  122. package/dist/interface/assets/{chevron-down-umZ7i0mG.js → chevron-down-D111daTn.js} +1 -1
  123. package/dist/interface/assets/{clock-outline-CbvOAMhO.js → clock-outline-DF1wLNzs.js} +1 -1
  124. package/dist/interface/assets/{close-CtaDF28n.js → close-BNAWPz0y.js} +1 -1
  125. package/dist/interface/assets/{close-circle-FZ8IxGd4.js → close-circle-zhDWvz98.js} +1 -1
  126. package/dist/interface/assets/{cloud-check-CFSukfAF.js → cloud-check-pUK1Fpt9.js} +1 -1
  127. package/dist/interface/assets/cloudHandoff-DNKMEHOI.js +1 -0
  128. package/dist/interface/assets/{config-BZphegxi.js → config-DTGhJmsj.js} +1 -1
  129. package/dist/interface/assets/{copy-CFA_pDRv.js → copy-BPT84cDt.js} +1 -1
  130. package/dist/interface/assets/{cube-scan-DEuMi23T.js → cube-scan-DOe6W9mW.js} +1 -1
  131. package/dist/interface/assets/{delete-921w_nKy.js → delete-BF6keuqy.js} +1 -1
  132. package/dist/interface/assets/{deployed-code-update-CYS6eKfa.js → deployed-code-update-xHE-blDN.js} +1 -1
  133. package/dist/interface/assets/{dist-BwEXwXSw.js → dist-Yc5s0_JB.js} +1 -1
  134. package/dist/interface/assets/{download-C-LzNRmM.js → download-BCPfm6aN.js} +1 -1
  135. package/dist/interface/assets/esm-B3yVlCMw.js +1 -0
  136. package/dist/interface/assets/esm-BKQ7CQK7.js +1 -0
  137. package/dist/interface/assets/esm-BiSE05P9.js +1 -0
  138. package/dist/interface/assets/esm-BoPthGAl.js +1 -0
  139. package/dist/interface/assets/esm-C2ALrdyx.js +1 -0
  140. package/dist/interface/assets/esm-CKEGzys4.js +1 -0
  141. package/dist/interface/assets/esm-CctiCHtK.js +1 -0
  142. package/dist/interface/assets/esm-Cqq81lnk.js +1 -0
  143. package/dist/interface/assets/esm-CyrLQTu0.js +1 -0
  144. package/dist/interface/assets/esm-D6O-eZYo.js +1 -0
  145. package/dist/interface/assets/esm-DG1f0qwo.js +1 -0
  146. package/dist/interface/assets/esm-DGegIZMF.js +1 -0
  147. package/dist/interface/assets/esm-JGwpHVqo.js +1 -0
  148. package/dist/interface/assets/esm-TRigYTsA.js +1 -0
  149. package/dist/interface/assets/{eye-off-DESV3QdF.js → eye-off-CaRq7Ks2.js} +1 -1
  150. package/dist/interface/assets/{flowSchema-_RiPAgMv.js → flowSchema-zo1H4tnP.js} +1 -1
  151. package/dist/interface/assets/{history-60iCpGvQ.js → history-SuH8IHAj.js} +1 -1
  152. package/dist/interface/assets/{home-w5iY2RUg.js → home-CUykMSBW.js} +1 -1
  153. package/dist/interface/assets/{information-outline-CvBsGtDu.js → information-outline-BQDq8w2t.js} +1 -1
  154. package/dist/interface/assets/{lightbulb-outline-DLrnCPG5.js → lightbulb-outline-ClK17CO6.js} +1 -1
  155. package/dist/interface/assets/main-CcvCf5qj.js +3 -0
  156. package/dist/interface/assets/{main-DJb49Tjp.css → main-XQ5Vahbs.css} +1 -1
  157. package/dist/interface/assets/{microphone-DUVI-s2_.js → microphone-C0weJY9W.js} +1 -1
  158. package/dist/interface/assets/minus-RI3VlDe8.js +1 -0
  159. package/dist/interface/assets/mqtt-CYc8_9pb.js +1 -0
  160. package/dist/interface/assets/native-B01iGjCh.js +1 -0
  161. package/dist/interface/assets/native-D381pxlG.js +1 -0
  162. package/dist/interface/assets/{nodeDefinitions-BecZ8I2Q.js → nodeDefinitions-DQQlFmPN.js} +1 -1
  163. package/dist/interface/assets/{notifications-CK6XQBF-.js → notifications-cHS8-1HN.js} +1 -1
  164. package/dist/interface/assets/{pencil-outline-BrOrbuzc.js → pencil-outline-D7aD4cCo.js} +1 -1
  165. package/dist/interface/assets/plugin-W20ihuog.js +1 -0
  166. package/dist/interface/assets/plugins-CaKErv4E.js +1 -0
  167. package/dist/interface/assets/{plus-Dd-XLT76.js → plus-CA5o30dE.js} +1 -1
  168. package/dist/interface/assets/{plus-CL6KSxf8.js → plus-DHwFyXkb.js} +1 -1
  169. package/dist/interface/assets/{power-lCbm_7y7.js → power-C9UIp2oO.js} +1 -1
  170. package/dist/interface/assets/{ring-resize-CEqUkpxT.js → ring-resize-DkY5EgVl.js} +1 -1
  171. package/dist/interface/assets/{round-alt-arrow-left-bold-CwaLYdW5.js → round-alt-arrow-left-bold-BxX4ufd0.js} +1 -1
  172. package/dist/interface/assets/{round-restart-alt-BFgY3k77.js → round-restart-alt-DPYbDt-x.js} +1 -1
  173. package/dist/interface/assets/{search-CT2BLw7G.js → search-BZkSqZO5.js} +1 -1
  174. package/dist/interface/assets/sensorIcons-DepqfSoA.js +1 -0
  175. package/dist/interface/assets/sensors-CMpbwMO4.js +1 -0
  176. package/dist/interface/assets/{server-BSYs0zoo.js → server-C-WV93FX.js} +1 -1
  177. package/dist/interface/assets/{settings-CzS4dvIO.js → settings-BUEZ5iRE.js} +1 -1
  178. package/dist/interface/assets/{source-branch-C6p1G3a9.js → source-branch-ztDB0e13.js} +1 -1
  179. package/dist/interface/assets/{table-2-line-_VC4NuFA.js → table-2-line-B-z0xvbG.js} +1 -1
  180. package/dist/interface/assets/{theme-Dr_YO8-0.js → theme-BkwBz73p.js} +1 -1
  181. package/dist/interface/assets/{trash-2-DcOYT3oH.js → trash-2-DMMlSPXn.js} +1 -1
  182. package/dist/interface/assets/{trash-can-outline-cphfB8Jh.js → trash-can-outline-DLKniIWM.js} +1 -1
  183. package/dist/interface/assets/{trash-fill-CRBaUdPn.js → trash-fill-DevIK050.js} +1 -1
  184. package/dist/interface/assets/{trash2-CvhB8xOW.js → trash2-BLScx4HX.js} +1 -1
  185. package/dist/interface/assets/{types-3mdj4rRK.js → types-Cko7VOxd.js} +1 -1
  186. package/dist/interface/assets/types-ClTvDPjn.js +1 -0
  187. package/dist/interface/assets/{types-YwmhC3Ej.js → types-vaT6wuY0.js} +1 -1
  188. package/dist/interface/assets/{upload-DeN3O-ua.js → upload-ClkX9wUX.js} +1 -1
  189. package/dist/interface/assets/{useAppVersion-UIA6seZv.js → useAppVersion-V1S18l98.js} +1 -1
  190. package/dist/interface/assets/useBackupRestore-BZ73vHrV.js +1 -0
  191. package/dist/interface/assets/{useCameraOptions-Dx-zyqdH.js → useCameraOptions-o1hYGLbC.js} +1 -1
  192. package/dist/interface/assets/{useElectron-BXVcamD0.js → useElectron-3ZJLtRk3.js} +1 -1
  193. package/dist/interface/assets/{useLogsSocket-DSxzAvQF.js → useLogsSocket-DDgnQ_Dk.js} +1 -1
  194. package/dist/interface/assets/{usePermissions-B_C-zX5H.js → usePermissions-BWlj5SzG.js} +1 -1
  195. package/dist/interface/assets/{usePluginUpdates-QU3U82S_.js → usePluginUpdates-DI1p2NMc.js} +1 -1
  196. package/dist/interface/assets/{useServerRestart-BxDBO7k-.js → useServerRestart-D_ASBw_0.js} +1 -1
  197. package/dist/interface/assets/{useStreamStatus-DY4NM_Ua.js → useStreamStatus-BQJIFFLv.js} +1 -1
  198. package/dist/interface/assets/useUpdateChannel-CyLSUSAY.js +1 -0
  199. package/dist/interface/assets/useUserOptions-Ds1Ybn7N.js +1 -0
  200. package/dist/interface/assets/{variable-oLSsiEtj.js → variable-CCMnQpL2.js} +1 -1
  201. package/dist/interface/assets/{vendor-JQXDMBA-.js → vendor-BaiDFVEr.js} +17 -16
  202. package/dist/interface/assets/vendor-cameraui-CQTIVF_m.js +2326 -0
  203. package/dist/interface/assets/{vendor-capacitor-CDwgXF4b.js → vendor-capacitor-4nn-eF9U.js} +2 -2
  204. package/dist/interface/assets/{vendor-chart-KrNcA52y.js → vendor-chart-DtwjR6yw.js} +1 -1
  205. package/dist/interface/assets/vendor-core-DDtZhtY9.js +1 -0
  206. package/dist/interface/assets/{vendor-dnd-Jch9IvL6.js → vendor-dnd-ChrDrMuz.js} +1 -1
  207. package/dist/interface/assets/{vendor-draggabilly-Cn-knCpG.js → vendor-draggabilly-DSeIE_bQ.js} +1 -1
  208. package/dist/interface/assets/{vendor-markdown-BhFLJolW.js → vendor-markdown--U0EK8HV.js} +1 -1
  209. package/dist/interface/assets/{vendor-primevue-C0acGg0Y.js → vendor-primevue-DE-f4Z5f.js} +76 -76
  210. package/dist/interface/assets/{vendor-vueflow-DQrTmoNS.js → vendor-vueflow-CLJNLJXc.js} +1 -1
  211. package/dist/interface/assets/web-BNRwhIOt.js +1 -0
  212. package/dist/interface/assets/web-BPkOXv4d.js +1 -0
  213. package/dist/interface/assets/web-BZIx_2d3.js +1 -0
  214. package/dist/interface/assets/web-BjKL51lK-BwChM7zd.js +1 -0
  215. package/dist/interface/assets/web-BkmtZjSt.js +1 -0
  216. package/dist/interface/assets/web-C6RgriWz.js +1 -0
  217. package/dist/interface/assets/web-CQFMLa0a.js +1 -0
  218. package/dist/interface/assets/web-CZGnd6VE.js +1 -0
  219. package/dist/interface/assets/web-Cfzay11X.js +1 -0
  220. package/dist/interface/assets/web-DAgBwKL-.js +1 -0
  221. package/dist/interface/assets/web-DgVHh5ek.js +1 -0
  222. package/dist/interface/assets/web-DlSXwZBR.js +1 -0
  223. package/dist/interface/assets/web-eDYxVGH7.js +1 -0
  224. package/dist/interface/assets/web-h4k3EoRQ.js +1 -0
  225. package/dist/interface/assets/{webhook-CMAB4nTl.js → webhook-DQiZUPv8.js} +1 -1
  226. package/dist/interface/assets/workbox-window.prod.es5-CcJiPjAS.js +1 -0
  227. package/dist/interface/assets/{zoom-in-STm8SNt2.js → zoom-in-Du1IB9oA.js} +1 -1
  228. package/dist/interface/index.html +42 -41
  229. package/dist/interface/sw.js +1 -1
  230. package/dist/server/package.json +14 -14
  231. package/dist/server/requirements.txt +2 -2
  232. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/__init__.py +6 -0
  233. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/__init__.py +0 -2
  234. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/events.py +11 -47
  235. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/frames.py +2 -4
  236. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/internal/sensor_rpc.py +6 -0
  237. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/contract.py +1 -1
  238. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/plugin/notifier.py +7 -0
  239. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/base.py +18 -1
  240. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/classifier.py +14 -8
  241. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/face.py +23 -7
  242. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/license_plate.py +23 -7
  243. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/storage/__init__.py +60 -2
  244. package/dist/server/src/api/controllers/automations.controller.d.ts +3 -1
  245. package/dist/server/src/api/controllers/automations.controller.js +27 -0
  246. package/dist/server/src/api/controllers/automations.controller.js.map +1 -1
  247. package/dist/server/src/api/controllers/cameras.controller.d.ts +3 -2
  248. package/dist/server/src/api/controllers/cameras.controller.js +26 -1
  249. package/dist/server/src/api/controllers/cameras.controller.js.map +1 -1
  250. package/dist/server/src/api/controllers/instances.controller.d.ts +2 -1
  251. package/dist/server/src/api/controllers/instances.controller.js +9 -0
  252. package/dist/server/src/api/controllers/instances.controller.js.map +1 -1
  253. package/dist/server/src/api/controllers/nvr.controller.d.ts +0 -3
  254. package/dist/server/src/api/controllers/nvr.controller.js +8 -38
  255. package/dist/server/src/api/controllers/nvr.controller.js.map +1 -1
  256. package/dist/server/src/api/controllers/plugins.controller.d.ts +9 -2
  257. package/dist/server/src/api/controllers/plugins.controller.js +156 -99
  258. package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
  259. package/dist/server/src/api/controllers/sensors.controller.d.ts +3 -1
  260. package/dist/server/src/api/controllers/sensors.controller.js +31 -0
  261. package/dist/server/src/api/controllers/sensors.controller.js.map +1 -1
  262. package/dist/server/src/api/database/index.d.ts +3 -2
  263. package/dist/server/src/api/database/index.js +12 -2
  264. package/dist/server/src/api/database/index.js.map +1 -1
  265. package/dist/server/src/api/database/migrations/v2-0-50.js +2 -1
  266. package/dist/server/src/api/database/migrations/v2-0-50.js.map +1 -1
  267. package/dist/server/src/api/database/migrations/v2-1-1.d.ts +3 -0
  268. package/dist/server/src/api/database/migrations/v2-1-1.js +35 -0
  269. package/dist/server/src/api/database/migrations/v2-1-1.js.map +1 -0
  270. package/dist/server/src/api/database/migrations/v2-1-4.d.ts +3 -0
  271. package/dist/server/src/api/database/migrations/v2-1-4.js +32 -0
  272. package/dist/server/src/api/database/migrations/v2-1-4.js.map +1 -0
  273. package/dist/server/src/api/database/record-schemas.d.ts +3 -0
  274. package/dist/server/src/api/database/record-schemas.js +1 -0
  275. package/dist/server/src/api/database/record-schemas.js.map +1 -1
  276. package/dist/server/src/api/database/types.d.ts +5 -0
  277. package/dist/server/src/api/routes/automations.routes.js +23 -1
  278. package/dist/server/src/api/routes/automations.routes.js.map +1 -1
  279. package/dist/server/src/api/routes/cameras.routes.js +15 -3
  280. package/dist/server/src/api/routes/cameras.routes.js.map +1 -1
  281. package/dist/server/src/api/routes/instances.routes.js +12 -1
  282. package/dist/server/src/api/routes/instances.routes.js.map +1 -1
  283. package/dist/server/src/api/routes/plugins.routes.js +36 -2
  284. package/dist/server/src/api/routes/plugins.routes.js.map +1 -1
  285. package/dist/server/src/api/routes/sensors.routes.js +23 -1
  286. package/dist/server/src/api/routes/sensors.routes.js.map +1 -1
  287. package/dist/server/src/api/schemas/automations.schema.d.ts +11 -0
  288. package/dist/server/src/api/schemas/automations.schema.js +7 -0
  289. package/dist/server/src/api/schemas/automations.schema.js.map +1 -1
  290. package/dist/server/src/api/schemas/cameras.schema.d.ts +33 -24
  291. package/dist/server/src/api/schemas/cameras.schema.js +18 -5
  292. package/dist/server/src/api/schemas/cameras.schema.js.map +1 -1
  293. package/dist/server/src/api/schemas/config.schema.d.ts +1 -0
  294. package/dist/server/src/api/schemas/config.schema.js +1 -0
  295. package/dist/server/src/api/schemas/config.schema.js.map +1 -1
  296. package/dist/server/src/api/schemas/instances.schema.d.ts +4 -0
  297. package/dist/server/src/api/schemas/instances.schema.js +3 -0
  298. package/dist/server/src/api/schemas/instances.schema.js.map +1 -1
  299. package/dist/server/src/api/schemas/plugins.schema.d.ts +11 -0
  300. package/dist/server/src/api/schemas/plugins.schema.js +6 -0
  301. package/dist/server/src/api/schemas/plugins.schema.js.map +1 -1
  302. package/dist/server/src/api/schemas/sensors.schema.d.ts +11 -0
  303. package/dist/server/src/api/schemas/sensors.schema.js +7 -0
  304. package/dist/server/src/api/schemas/sensors.schema.js.map +1 -1
  305. package/dist/server/src/api/schemas/users.schema.d.ts +12 -0
  306. package/dist/server/src/api/schemas/users.schema.js +4 -0
  307. package/dist/server/src/api/schemas/users.schema.js.map +1 -1
  308. package/dist/server/src/api/services/auth.service.js +28 -23
  309. package/dist/server/src/api/services/auth.service.js.map +1 -1
  310. package/dist/server/src/api/services/automations.service.js +36 -36
  311. package/dist/server/src/api/services/automations.service.js.map +1 -1
  312. package/dist/server/src/api/services/backup.service.js +29 -26
  313. package/dist/server/src/api/services/backup.service.js.map +1 -1
  314. package/dist/server/src/api/services/backupScheduler.service.js +1 -2
  315. package/dist/server/src/api/services/backupScheduler.service.js.map +1 -1
  316. package/dist/server/src/api/services/cameras.service.js +222 -173
  317. package/dist/server/src/api/services/cameras.service.js.map +1 -1
  318. package/dist/server/src/api/services/instances.service.d.ts +7 -0
  319. package/dist/server/src/api/services/instances.service.js +17 -0
  320. package/dist/server/src/api/services/instances.service.js.map +1 -1
  321. package/dist/server/src/api/services/mqtt.service.js +1 -2
  322. package/dist/server/src/api/services/mqtt.service.js.map +1 -1
  323. package/dist/server/src/api/services/notifications.service.d.ts +1 -0
  324. package/dist/server/src/api/services/notifications.service.js +3 -0
  325. package/dist/server/src/api/services/notifications.service.js.map +1 -1
  326. package/dist/server/src/api/services/plugins.service.js +1 -1
  327. package/dist/server/src/api/services/plugins.service.js.map +1 -1
  328. package/dist/server/src/api/services/remote.service.js +26 -25
  329. package/dist/server/src/api/services/remote.service.js.map +1 -1
  330. package/dist/server/src/api/services/sensors.service.d.ts +1 -0
  331. package/dist/server/src/api/services/sensors.service.js +1 -0
  332. package/dist/server/src/api/services/sensors.service.js.map +1 -1
  333. package/dist/server/src/api/services/server.service.js +9 -7
  334. package/dist/server/src/api/services/server.service.js.map +1 -1
  335. package/dist/server/src/api/services/shares.service.js +19 -14
  336. package/dist/server/src/api/services/shares.service.js.map +1 -1
  337. package/dist/server/src/api/services/users.service.js +159 -105
  338. package/dist/server/src/api/services/users.service.js.map +1 -1
  339. package/dist/server/src/api/services/workers.service.d.ts +1 -0
  340. package/dist/server/src/api/services/workers.service.js +55 -45
  341. package/dist/server/src/api/services/workers.service.js.map +1 -1
  342. package/dist/server/src/api/types/index.d.ts +38 -5
  343. package/dist/server/src/api/types/index.js.map +1 -1
  344. package/dist/server/src/api/utils/bulk.d.ts +9 -0
  345. package/dist/server/src/api/utils/bulk.js +27 -0
  346. package/dist/server/src/api/utils/bulk.js.map +1 -0
  347. package/dist/server/src/api/utils/cert.js +8 -0
  348. package/dist/server/src/api/utils/cert.js.map +1 -1
  349. package/dist/server/src/api/websocket/nsp/server.js +1 -1
  350. package/dist/server/src/api/websocket/nsp/server.js.map +1 -1
  351. package/dist/server/src/automations/conditions/sensorState.js +9 -0
  352. package/dist/server/src/automations/conditions/sensorState.js.map +1 -1
  353. package/dist/server/src/camera/controller.d.ts +1 -1
  354. package/dist/server/src/camera/controller.js +12 -11
  355. package/dist/server/src/camera/controller.js.map +1 -1
  356. package/dist/server/src/camera/decoder/child.d.ts +1 -0
  357. package/dist/server/src/camera/decoder/child.js +14 -1
  358. package/dist/server/src/camera/decoder/child.js.map +1 -1
  359. package/dist/server/src/camera/decoder/debug/detection-record.d.ts +42 -0
  360. package/dist/server/src/camera/decoder/debug/detection-record.js +103 -0
  361. package/dist/server/src/camera/decoder/debug/detection-record.js.map +1 -0
  362. package/dist/server/src/camera/decoder/debug/perf-tracker.d.ts +20 -0
  363. package/dist/server/src/camera/decoder/debug/perf-tracker.js +82 -0
  364. package/dist/server/src/camera/decoder/debug/perf-tracker.js.map +1 -0
  365. package/dist/server/src/camera/decoder/detection-coordinator.d.ts +28 -6
  366. package/dist/server/src/camera/decoder/detection-coordinator.js +452 -76
  367. package/dist/server/src/camera/decoder/detection-coordinator.js.map +1 -1
  368. package/dist/server/src/camera/decoder/detection-pipeline.d.ts +7 -20
  369. package/dist/server/src/camera/decoder/detection-pipeline.js +67 -127
  370. package/dist/server/src/camera/decoder/detection-pipeline.js.map +1 -1
  371. package/dist/server/src/camera/decoder/event-manager.d.ts +42 -14
  372. package/dist/server/src/camera/decoder/event-manager.js +304 -217
  373. package/dist/server/src/camera/decoder/event-manager.js.map +1 -1
  374. package/dist/server/src/camera/decoder/event-thumbnailer.d.ts +5 -8
  375. package/dist/server/src/camera/decoder/event-thumbnailer.js +11 -21
  376. package/dist/server/src/camera/decoder/event-thumbnailer.js.map +1 -1
  377. package/dist/server/src/camera/decoder/frame-scaler.d.ts +2 -1
  378. package/dist/server/src/camera/decoder/frame-scaler.js +9 -0
  379. package/dist/server/src/camera/decoder/frame-scaler.js.map +1 -1
  380. package/dist/server/src/camera/decoder/moment-crop.d.ts +30 -0
  381. package/dist/server/src/camera/decoder/moment-crop.js +86 -0
  382. package/dist/server/src/camera/decoder/moment-crop.js.map +1 -0
  383. package/dist/server/src/camera/decoder/nvr-sink.d.ts +38 -0
  384. package/dist/server/src/camera/decoder/nvr-sink.js +36 -0
  385. package/dist/server/src/camera/decoder/nvr-sink.js.map +1 -0
  386. package/dist/server/src/camera/decoder/secondary-stage.d.ts +4 -2
  387. package/dist/server/src/camera/decoder/secondary-stage.js +58 -96
  388. package/dist/server/src/camera/decoder/secondary-stage.js.map +1 -1
  389. package/dist/server/src/camera/decoder/sources/analysis-source.d.ts +10 -0
  390. package/dist/server/src/camera/decoder/sources/analysis-source.js +2 -0
  391. package/dist/server/src/camera/decoder/sources/analysis-source.js.map +1 -0
  392. package/dist/server/src/camera/decoder/sources/{snapshot-source.d.ts → buffered-source.d.ts} +17 -5
  393. package/dist/server/src/camera/decoder/sources/{snapshot-source.js → buffered-source.js} +81 -24
  394. package/dist/server/src/camera/decoder/sources/buffered-source.js.map +1 -0
  395. package/dist/server/src/camera/decoder/sources/frame-source.d.ts +4 -7
  396. package/dist/server/src/camera/decoder/sources/frame-source.js +4 -7
  397. package/dist/server/src/camera/decoder/sources/frame-source.js.map +1 -1
  398. package/dist/server/src/camera/decoder/types.d.ts +1 -0
  399. package/dist/server/src/camera/decoder/types.js.map +1 -1
  400. package/dist/server/src/camera/decoder/worker.js +15 -3
  401. package/dist/server/src/camera/decoder/worker.js.map +1 -1
  402. package/dist/server/src/internal-bus.d.ts +1 -1
  403. package/dist/server/src/internal-bus.js.map +1 -1
  404. package/dist/server/src/main.js +1 -1
  405. package/dist/server/src/main.js.map +1 -1
  406. package/dist/server/src/manager/discoveryManager.js +0 -11
  407. package/dist/server/src/manager/discoveryManager.js.map +1 -1
  408. package/dist/server/src/manager/notificationManager.d.ts +1 -1
  409. package/dist/server/src/manager/notificationManager.js +60 -41
  410. package/dist/server/src/manager/notificationManager.js.map +1 -1
  411. package/dist/server/src/mqtt/bridge.d.ts +2 -0
  412. package/dist/server/src/mqtt/bridge.js +39 -35
  413. package/dist/server/src/mqtt/bridge.js.map +1 -1
  414. package/dist/server/src/plugins/nvr.d.ts +2 -0
  415. package/dist/server/src/plugins/nvr.js +17 -0
  416. package/dist/server/src/plugins/nvr.js.map +1 -0
  417. package/dist/server/src/plugins/runtime/node/proxy/sensorManager.js +1 -1
  418. package/dist/server/src/plugins/runtime/node/proxy/sensorManager.js.map +1 -1
  419. package/dist/server/src/plugins/runtime/python/storage.py +18 -1
  420. package/dist/server/src/plugins/runtime/python/store.py +7 -1
  421. package/dist/server/src/plugins/schema.d.ts +2 -1
  422. package/dist/server/src/plugins/schema.js +66 -6
  423. package/dist/server/src/plugins/schema.js.map +1 -1
  424. package/dist/server/src/plugins/store/storeFile.js +10 -2
  425. package/dist/server/src/plugins/store/storeFile.js.map +1 -1
  426. package/dist/server/src/remote/services/index.js +1 -1
  427. package/dist/server/src/remote/services/index.js.map +1 -1
  428. package/dist/server/src/rpc/interfaces/frameworker.d.ts +1 -0
  429. package/dist/server/src/rpc/interfaces/sensor.d.ts +2 -0
  430. package/dist/server/src/rpc/server.js +2 -0
  431. package/dist/server/src/rpc/server.js.map +1 -1
  432. package/dist/server/src/sensors/registry.js +7 -2
  433. package/dist/server/src/sensors/registry.js.map +1 -1
  434. package/dist/server/src/sensors/sensor.js +13 -1
  435. package/dist/server/src/sensors/sensor.js.map +1 -1
  436. package/dist/server/src/services/config/constants.js +1 -0
  437. package/dist/server/src/services/config/constants.js.map +1 -1
  438. package/dist/server/src/services/config/index.d.ts +5 -2
  439. package/dist/server/src/services/config/index.js +38 -5
  440. package/dist/server/src/services/config/index.js.map +1 -1
  441. package/dist/server/src/services/config/types.d.ts +4 -0
  442. package/dist/server/src/utils/path.d.ts +1 -0
  443. package/dist/server/src/utils/path.js +33 -0
  444. package/dist/server/src/utils/path.js.map +1 -1
  445. package/dist/server/src/workers/capabilities/frame-decoding.js +1 -1
  446. package/dist/server/src/workers/capabilities/frame-decoding.js.map +1 -1
  447. package/package.json +14 -14
  448. package/dist/interface/assets/Automations-DBjwNb3F.js +0 -2
  449. package/dist/interface/assets/Camera-BfvpjkW3.js +0 -2
  450. package/dist/interface/assets/Camera-yUrhUGmO.css +0 -1
  451. package/dist/interface/assets/Camview-DArvg940.js +0 -1
  452. package/dist/interface/assets/Camview-mLCaY0ld.css +0 -1
  453. package/dist/interface/assets/Config-Ccp5Acpv.js +0 -2
  454. package/dist/interface/assets/ConfigConditionSensorState-lI9dzHiT.js +0 -1
  455. package/dist/interface/assets/ConfigSensorValueInput-DW4er753.js +0 -1
  456. package/dist/interface/assets/ConfigTriggerSensor-vhwPNmPj.js +0 -1
  457. package/dist/interface/assets/Console-C6yUdEaM.js +0 -1
  458. package/dist/interface/assets/CuiAutomationRunsDialog-C4i7y1Re.js +0 -1
  459. package/dist/interface/assets/CuiBottomSheet-C2zU_iyj.js +0 -1
  460. package/dist/interface/assets/CuiCameraPipCard-CZ-oDxzy.js +0 -1
  461. package/dist/interface/assets/CuiCameraRecordings-BHj7CUE7.css +0 -1
  462. package/dist/interface/assets/CuiCameraRecordings-mY_giLEi.js +0 -1
  463. package/dist/interface/assets/CuiLightControl-CEpcKss7.js +0 -1
  464. package/dist/interface/assets/CuiMarkdownContent-C2uBepC1.js +0 -1
  465. package/dist/interface/assets/CuiMarkdownContent-QxLR7_qs.js +0 -1
  466. package/dist/interface/assets/CuiPluginCard-1dSDwOCf.js +0 -2
  467. package/dist/interface/assets/CuiRecordingsGrid-COHg3ZCT.css +0 -1
  468. package/dist/interface/assets/CuiRecordingsGrid-CkwE3jcR.js +0 -1
  469. package/dist/interface/assets/CuiSchema-DKATswRc.js +0 -1
  470. package/dist/interface/assets/Faces-BeeZrFV-.js +0 -1
  471. package/dist/interface/assets/FirstSteps-DWT6Tt_T.js +0 -1
  472. package/dist/interface/assets/Instances-CJlFo8ni.js +0 -1
  473. package/dist/interface/assets/Menu-DP0aMICW.js +0 -1
  474. package/dist/interface/assets/OAuthDeviceFlow-CcSkntGk.js +0 -1
  475. package/dist/interface/assets/Plugin-8dbt_8iG.js +0 -1
  476. package/dist/interface/assets/Plugin-BLqyZrJP.css +0 -1
  477. package/dist/interface/assets/PluginDetail-C9dR9jrw.js +0 -2
  478. package/dist/interface/assets/PluginSearch-BVAtgBZs.js +0 -1
  479. package/dist/interface/assets/PluginSearch-HEf_6CrR.js +0 -2
  480. package/dist/interface/assets/Plugins-CQJhji6o.js +0 -1
  481. package/dist/interface/assets/Recordings-AD78njIA.js +0 -1
  482. package/dist/interface/assets/SensorEdit-rC02usEO.js +0 -1
  483. package/dist/interface/assets/Sensors-CFfII3-e.css +0 -1
  484. package/dist/interface/assets/Sensors-Vwr7MYz6.js +0 -2
  485. package/dist/interface/assets/SettingsAccount-BBsivYFf.js +0 -1
  486. package/dist/interface/assets/SettingsAccount-CN9Xcgt-.js +0 -1
  487. package/dist/interface/assets/SettingsAppearance-Qh1cw9iX.js +0 -1
  488. package/dist/interface/assets/SettingsBackup-DNDDU6a1.js +0 -1
  489. package/dist/interface/assets/SettingsList-tFKUMnsB.js +0 -1
  490. package/dist/interface/assets/SettingsMqtt-BYVV1Mew.js +0 -1
  491. package/dist/interface/assets/SettingsRecordings-B4DDJSKe.js +0 -1
  492. package/dist/interface/assets/SettingsRemote-Bib7kXto.js +0 -1
  493. package/dist/interface/assets/SettingsSystem-DIe7CSgH.js +0 -2
  494. package/dist/interface/assets/Terminal-DuJHIlLe.js +0 -4
  495. package/dist/interface/assets/VersionsHandler-D9sDkGXx.js +0 -7
  496. package/dist/interface/assets/Workers-fV_NEZ7U.js +0 -2
  497. package/dist/interface/assets/api-Draww2tC.js +0 -2
  498. package/dist/interface/assets/api-eELh8KCM.css +0 -2
  499. package/dist/interface/assets/automations-BfsdbSPC.js +0 -1
  500. package/dist/interface/assets/cameras.schema-DMY4SYte.js +0 -1
  501. package/dist/interface/assets/chevron-right-AhqYJOFy.js +0 -1
  502. package/dist/interface/assets/cloudHandoff-BQsDy9yp.js +0 -1
  503. package/dist/interface/assets/esm-B1LZs0VG.js +0 -1
  504. package/dist/interface/assets/esm-BB4SBaek.js +0 -1
  505. package/dist/interface/assets/esm-BGA8Ydne.js +0 -1
  506. package/dist/interface/assets/esm-BHI_KH7L.js +0 -1
  507. package/dist/interface/assets/esm-BQ0EuuZe.js +0 -1
  508. package/dist/interface/assets/esm-Bfb-tuKt.js +0 -1
  509. package/dist/interface/assets/esm-BzR_6ma5.js +0 -1
  510. package/dist/interface/assets/esm-CCIqNfsh.js +0 -1
  511. package/dist/interface/assets/esm-CSMN-8o1.js +0 -1
  512. package/dist/interface/assets/esm-CxWbrBxP.js +0 -1
  513. package/dist/interface/assets/esm-DBTrmJK6.js +0 -1
  514. package/dist/interface/assets/esm-DRswZUWf.js +0 -1
  515. package/dist/interface/assets/esm-Dk7gxPHs.js +0 -1
  516. package/dist/interface/assets/esm-P0RCkAtk.js +0 -1
  517. package/dist/interface/assets/main-CV7qCZ5i.js +0 -3
  518. package/dist/interface/assets/mqtt-BPfLOT7L.js +0 -1
  519. package/dist/interface/assets/native-Cr4dkfqy.js +0 -1
  520. package/dist/interface/assets/native-D1Vvlhds.js +0 -1
  521. package/dist/interface/assets/plugin-937qnq7E.js +0 -1
  522. package/dist/interface/assets/plugins-BU7TQh_f.js +0 -1
  523. package/dist/interface/assets/sensorIcons-DtJEfoU4.js +0 -1
  524. package/dist/interface/assets/sensors-DjgfMS8S.js +0 -1
  525. package/dist/interface/assets/types-BGMvANrz.js +0 -1
  526. package/dist/interface/assets/useBackupRestore-E3pVEOvA.js +0 -1
  527. package/dist/interface/assets/useCardSelection-DGPLn1ZH.js +0 -1
  528. package/dist/interface/assets/useUserOptions-BL53bECb.js +0 -1
  529. package/dist/interface/assets/vendor-cameraui-DojVuZ2L.js +0 -2326
  530. package/dist/interface/assets/vendor-core-ZDcIKAw9.js +0 -1
  531. package/dist/interface/assets/web-BQtDHNew.js +0 -1
  532. package/dist/interface/assets/web-BY9kjyTj.js +0 -1
  533. package/dist/interface/assets/web-BcQtDSat.js +0 -1
  534. package/dist/interface/assets/web-BgrRQzLO.js +0 -1
  535. package/dist/interface/assets/web-BjKL51lK-CJYmHsnY.js +0 -1
  536. package/dist/interface/assets/web-BxvsJylk.js +0 -1
  537. package/dist/interface/assets/web-C-3iwDhG.js +0 -1
  538. package/dist/interface/assets/web-C9XOwu07.js +0 -1
  539. package/dist/interface/assets/web-CPCxRDtw.js +0 -1
  540. package/dist/interface/assets/web-D0U5B2i2.js +0 -1
  541. package/dist/interface/assets/web-DtxjXJdS.js +0 -1
  542. package/dist/interface/assets/web-Duf-oV4e.js +0 -1
  543. package/dist/interface/assets/web-jy45nBi_.js +0 -1
  544. package/dist/interface/assets/web-vWx_-Iq5.js +0 -1
  545. package/dist/interface/assets/workbox-window.prod.es5-Dlqax_Po.js +0 -1
  546. package/dist/server/src/api/utils/moveFiles.d.ts +0 -4
  547. package/dist/server/src/api/utils/moveFiles.js +0 -37
  548. package/dist/server/src/api/utils/moveFiles.js.map +0 -1
  549. package/dist/server/src/camera/decoder/sources/snapshot-source.js.map +0 -1
  550. package/dist/server/src/camera/decoder/stationary-suppressor.d.ts +0 -38
  551. package/dist/server/src/camera/decoder/stationary-suppressor.js +0 -308
  552. package/dist/server/src/camera/decoder/stationary-suppressor.js.map +0 -1
@@ -1,10 +1,16 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { NamespaceManager } from '../../rpc/namespaces.js';
3
3
  import { boxIntersectsPolygon } from '../utils/filter.js';
4
+ import { detectionRecord } from './debug/detection-record.js';
5
+ import { leanEvent, NvrSink } from './nvr-sink.js';
4
6
  import { MAX_UNTRACKED_PLATES, normalizePlateText, PlateVoteTracker } from './plate-vote.js';
5
- import { STATIONARY_SPEED_THRESHOLD } from './stationary-suppressor.js';
7
+ export const MOMENT_RANK_OBJECT = 0;
8
+ export const MOMENT_RANK_ATTRIBUTE = 1;
6
9
  const UPDATE_THROTTLE_MS = 1000;
10
+ const MOMENT_IMPROVEMENT = 1.25;
11
+ const CLIP_ATTRIBUTE = 'clip';
7
12
  const MIN_MOVING_SPEED = 0.05;
13
+ const STATIONARY_SPEED_THRESHOLD = 0.002;
8
14
  function jpegInfo(jpeg) {
9
15
  let i = 2;
10
16
  while (i + 9 < jpeg.length) {
@@ -32,28 +38,35 @@ export class DetectionEventManager {
32
38
  proxy;
33
39
  logger;
34
40
  static MAX_PLATE_THUMBNAILS = 16;
41
+ static SEGMENT_LINGER_MS = 10_000;
35
42
  activeEvent = null;
36
43
  activeSegment = null;
37
- segmentTimer = null;
44
+ // first/last box center per track within the current segment, so the NVR
45
+ // can reason about where a subject entered and left the frame
46
+ segmentTrackPaths = new Map();
38
47
  segmentIndex = 0;
39
48
  lastPublishTime = 0;
40
- sceneThumbnail = null;
41
- sceneThumbnailShipped = false;
42
- detectionLabelThumbnails = new Map();
49
+ shippedSceneAt = 0;
43
50
  attributeThumbnails = new Map();
51
+ heldAttributes = [];
52
+ shippedAttributes = new Map();
53
+ segmentMoment;
54
+ pendingMoment;
55
+ eventThumbnailAt = 0;
56
+ segmentClosePendingSince = null;
57
+ lingerTimer = null;
58
+ onSegmentClosedCallback;
44
59
  eventThumbnail = null;
45
60
  needsEventThumbnail = false;
46
- eventBestShot = null;
47
- eventBestShotPushed = false;
48
- eventBestShotDirty = false;
49
61
  segmentFaceTrackIds = new Map();
50
62
  segmentPlateAttrIndex = new Map();
51
63
  segmentPlateReads = new Set();
52
64
  eventPlateVotes = new Map();
53
65
  plateVotingActive = true;
54
66
  segmentClassifierTrackIds = new Map();
55
- segmentClipTrackIds = new Set();
67
+ segmentClipLabels = new Map();
56
68
  eventSubject;
69
+ nvr;
57
70
  onEventEndCallback;
58
71
  constructor(cameraId, proxy, logger) {
59
72
  this.cameraId = cameraId;
@@ -61,10 +74,35 @@ export class DetectionEventManager {
61
74
  this.logger = logger;
62
75
  const ns = NamespaceManager.detectionEventNamespaces(cameraId);
63
76
  this.eventSubject = ns.detectionEventSubject;
77
+ this.nvr = new NvrSink(proxy, logger);
78
+ }
79
+ updateNvrRpc(namespace) {
80
+ this.nvr.setNamespace(namespace);
64
81
  }
65
82
  onEventEnd(callback) {
66
83
  this.onEventEndCallback = callback;
67
84
  }
85
+ onSegmentClosed(callback) {
86
+ this.onSegmentClosedCallback = callback;
87
+ }
88
+ offerMoment(moment) {
89
+ // the tick cuts the moment before it opens the segment, so the very picture
90
+ // that opens a span would be the one dropped; hold it for that opening
91
+ if (!this.activeSegment) {
92
+ // a tick can offer the object shot and then the face shot; within the tick
93
+ // they compete by rank, a newer tick always displaces the older pending one
94
+ if (this.beatsMoment(moment.rank, moment.score, moment.stream, this.incumbentMoment(moment.capturedAt))) {
95
+ this.pendingMoment = moment;
96
+ }
97
+ // debugging
98
+ this.recordMomentVerdict(moment, 'pending');
99
+ return;
100
+ }
101
+ this.takeMoment(moment);
102
+ }
103
+ wantsMoment(rank, score, stream, at) {
104
+ return this.beatsMoment(rank, score, stream, this.incumbentMoment(at));
105
+ }
68
106
  processResults(data) {
69
107
  const now = data.timestamp;
70
108
  const triggers = this.extractTriggers(data, now);
@@ -80,6 +118,7 @@ export class DetectionEventManager {
80
118
  // publish immediately, the UI shouldn't wait for the next throttled update
81
119
  if (data.eventThumbnail && this.needsEventThumbnail) {
82
120
  this.eventThumbnail = data.eventThumbnail;
121
+ this.eventThumbnailAt = now;
83
122
  this.needsEventThumbnail = false;
84
123
  this.publishEventThumbnail();
85
124
  }
@@ -95,11 +134,17 @@ export class DetectionEventManager {
95
134
  this.publishUpdateThrottled();
96
135
  }
97
136
  }
98
- if (hasDetections && data.hasCascadeTrigger) {
137
+ if (data.hasOpenSpans) {
138
+ this.segmentClosePendingSince = null;
139
+ if (this.lingerTimer) {
140
+ clearTimeout(this.lingerTimer);
141
+ this.lingerTimer = null;
142
+ }
99
143
  if (!this.activeSegment) {
100
- this.openSegment(data, now);
144
+ if (hasDetections)
145
+ this.openSegment(data, now);
101
146
  }
102
- else {
147
+ else if (hasDetections) {
103
148
  this.enrichSegment(data, now);
104
149
  if (data.thumbnails && data.thumbnails.length > 0) {
105
150
  this.updateThumbnails(data.thumbnails);
@@ -108,40 +153,48 @@ export class DetectionEventManager {
108
153
  this.updateTypes();
109
154
  this.publishSegmentThrottled('segment-update');
110
155
  }
111
- this.resetSegmentTimer(data.segmentTimeout);
112
156
  }
157
+ else if (this.activeSegment && this.segmentClosePendingSince === null) {
158
+ // all spans closed: linger before deciding, a reopening span continues
159
+ // this segment (detector flicker is not a new visit); lastSeen stays on
160
+ // the last real detection, timer-driven so tickless cameras close too
161
+ this.segmentClosePendingSince = now;
162
+ this.lingerTimer = setTimeout(() => {
163
+ this.lingerTimer = null;
164
+ if (this.segmentClosePendingSince === null)
165
+ return;
166
+ this.segmentClosePendingSince = null;
167
+ this.closeSegment();
168
+ this.onSegmentClosedCallback?.();
169
+ }, DetectionEventManager.SEGMENT_LINGER_MS);
170
+ }
171
+ }
172
+ hasActiveSegment() {
173
+ return this.activeSegment !== null;
113
174
  }
114
175
  forceEndActiveEvent() {
115
176
  if (this.activeEvent)
116
177
  this.endEvent();
117
178
  }
118
179
  destroy() {
119
- if (this.segmentTimer) {
120
- clearTimeout(this.segmentTimer);
121
- this.segmentTimer = null;
122
- }
123
180
  if (this.activeEvent)
124
181
  this.endEvent();
125
182
  }
126
- publishEventThumbnail(jpeg, source = 'scene') {
183
+ publishEventThumbnail(jpeg, capturedAt) {
127
184
  if (!this.activeEvent)
128
185
  return;
129
- // a late scene re-shoot (HQ warm-up) must not undo an object crop
130
- if (source === 'scene' && this.eventBestShotPushed)
131
- return;
132
186
  if (jpeg) {
133
187
  this.eventThumbnail = jpeg;
188
+ this.eventThumbnailAt = capturedAt ?? Date.now();
134
189
  this.needsEventThumbnail = false;
135
190
  }
136
191
  if (!this.eventThumbnail)
137
192
  return;
138
193
  this.logger.trace(`[event] thumbnail id=${this.activeEvent.id.slice(0, 8)} ${jpegInfo(this.eventThumbnail)}`);
139
194
  this.activeEvent.segments = [];
140
- this.activeEvent.thumbnail = this.eventThumbnail;
141
- this.publish('update');
142
- this.activeEvent.thumbnail = undefined;
143
- if (this.activeSegment && !this.sceneThumbnail) {
144
- this.sceneThumbnail = { jpeg: this.eventThumbnail, score: 0, area: 0, onEdge: false, hasAttribute: false };
195
+ this.activeEvent.thumbnailAt = this.eventThumbnailAt || undefined;
196
+ this.publish('update', { scene: this.eventThumbnail });
197
+ if (this.activeSegment && !this.segmentMoment) {
145
198
  this.publishSegment('segment-update');
146
199
  }
147
200
  }
@@ -166,39 +219,29 @@ export class DetectionEventManager {
166
219
  this.segmentIndex = 0;
167
220
  this.needsEventThumbnail = true;
168
221
  this.eventThumbnail = null;
169
- this.eventBestShot = null;
170
- this.eventBestShotPushed = false;
171
- this.eventBestShotDirty = false;
222
+ this.eventThumbnailAt = 0;
172
223
  if (data.eventThumbnail) {
173
224
  this.eventThumbnail = data.eventThumbnail;
225
+ this.eventThumbnailAt = now;
174
226
  this.needsEventThumbnail = false;
175
227
  }
176
228
  this.updateTypes();
177
- // pre-captured thumbnail rides inline in the start message, otherwise the
178
- // next coordinator tick delivers it via update
229
+ // a pre-captured scene ships with the start message, otherwise the next
230
+ // coordinator tick delivers it via update
179
231
  if (this.eventThumbnail) {
180
- this.activeEvent.thumbnail = this.eventThumbnail;
232
+ this.activeEvent.thumbnailAt = this.eventThumbnailAt || undefined;
181
233
  }
182
- this.publish('start');
183
- if (this.activeEvent)
184
- this.activeEvent.thumbnail = undefined;
234
+ this.publish('start', this.eventThumbnail ? { scene: this.eventThumbnail } : undefined);
185
235
  const triggerTypes = [...new Set(triggers.map((t) => t.type))].join(',');
186
236
  const thumbInfo = this.eventThumbnail ? jpegInfo(this.eventThumbnail) : 'pending';
187
237
  this.logger.log(`[event] start id=${this.activeEvent.id.slice(0, 8)} triggers=[${triggerTypes}] types=[${this.activeEvent.types.join(',')}] thumb=${thumbInfo}`);
188
- if (this.hasNewDetections(data) && data.hasCascadeTrigger) {
238
+ if (this.hasNewDetections(data) && data.hasOpenSpans) {
189
239
  this.openSegment(data, now);
190
- this.resetSegmentTimer(data.segmentTimeout);
191
240
  }
192
241
  }
193
242
  endEvent() {
194
243
  if (!this.activeEvent)
195
244
  return;
196
- if (this.eventBestShotDirty && this.eventBestShot) {
197
- this.publishEventThumbnail(this.eventBestShot.jpeg, 'best-shot');
198
- }
199
- this.eventBestShot = null;
200
- this.eventBestShotPushed = false;
201
- this.eventBestShotDirty = false;
202
245
  this.closeSegment();
203
246
  this.activeEvent.state = 'ended';
204
247
  this.activeEvent.endTime = Date.now();
@@ -211,11 +254,12 @@ export class DetectionEventManager {
211
254
  this.logger.log(`[event] end id=${this.activeEvent.id.slice(0, 8)} duration=${duration}ms segments=${this.segmentIndex} types=[${this.activeEvent.types.join(',')}]`);
212
255
  this.activeEvent = null;
213
256
  this.activeSegment = null;
214
- this.eventPlateVotes.clear();
215
- if (this.segmentTimer) {
216
- clearTimeout(this.segmentTimer);
217
- this.segmentTimer = null;
257
+ this.segmentClosePendingSince = null;
258
+ if (this.lingerTimer) {
259
+ clearTimeout(this.lingerTimer);
260
+ this.lingerTimer = null;
218
261
  }
262
+ this.eventPlateVotes.clear();
219
263
  if (this.onEventEndCallback) {
220
264
  this.onEventEndCallback();
221
265
  }
@@ -229,7 +273,15 @@ export class DetectionEventManager {
229
273
  detections: [],
230
274
  attributes: [],
231
275
  };
276
+ this.segmentTrackPaths = new Map();
232
277
  this.enrichSegment(data, now);
278
+ // the tick cuts its moment before it opens the segment, and both carry the
279
+ // tick's stamp, so an older one belongs to a tick that opened nothing
280
+ const pending = this.pendingMoment;
281
+ this.pendingMoment = undefined;
282
+ if (pending?.capturedAt === now) {
283
+ this.takeMoment(pending);
284
+ }
233
285
  if (data.thumbnails && data.thumbnails.length > 0) {
234
286
  this.updateThumbnails(data.thumbnails);
235
287
  }
@@ -250,7 +302,7 @@ export class DetectionEventManager {
250
302
  return;
251
303
  }
252
304
  this.segmentPlateAttrIndex.set(attrKey, this.activeSegment.attributes.length);
253
- this.activeSegment.attributes.push({ type: 'license_plate', label, confidence, parentTrackId });
305
+ this.pushAttribute({ type: 'license_plate', label, confidence, parentTrackId });
254
306
  }
255
307
  flushPlateFallbacks() {
256
308
  if (!this.activeSegment || !this.plateVotingActive)
@@ -272,16 +324,13 @@ export class DetectionEventManager {
272
324
  closeSegment() {
273
325
  if (!this.activeSegment || !this.activeEvent)
274
326
  return;
275
- this.activeSegment.lastSeen = Date.now();
327
+ // lastSeen stays on the last real detection: the linger only delays the
328
+ // decision to close, it is not part of what was seen
276
329
  this.flushPlateFallbacks();
277
330
  this.publishSegment('segment-end');
278
331
  this.clearSegmentThumbnails();
279
332
  this.segmentIndex++;
280
333
  this.activeSegment = null;
281
- if (this.segmentTimer) {
282
- clearTimeout(this.segmentTimer);
283
- this.segmentTimer = null;
284
- }
285
334
  }
286
335
  enrichTriggers(triggers, now) {
287
336
  if (!this.activeEvent)
@@ -304,10 +353,21 @@ export class DetectionEventManager {
304
353
  return;
305
354
  this.activeSegment.lastSeen = now;
306
355
  if (data.objects.length > 0) {
307
- // upsert per label, keep best score/box/trackId and maxCount
308
356
  const labelCounts = new Map();
309
357
  for (const obj of data.objects) {
310
358
  const t = obj;
359
+ if (t.trackId !== undefined && obj.box) {
360
+ const cx = obj.box.x + obj.box.width / 2;
361
+ const cy = obj.box.y + obj.box.height / 2;
362
+ const path = this.segmentTrackPaths.get(t.trackId);
363
+ if (path) {
364
+ path.exitX = cx;
365
+ path.exitY = cy;
366
+ }
367
+ else {
368
+ this.segmentTrackPaths.set(t.trackId, { enterX: cx, enterY: cy, exitX: cx, exitY: cy });
369
+ }
370
+ }
311
371
  const entry = labelCounts.get(obj.label);
312
372
  if (entry) {
313
373
  entry.count++;
@@ -344,6 +404,13 @@ export class DetectionEventManager {
344
404
  this.activeSegment.detections.push({ label, score: bestScore, maxCount: count, box: bestBox, trackId: bestTrackId, moving });
345
405
  }
346
406
  }
407
+ for (const d of this.activeSegment.detections) {
408
+ if (d.trackId === undefined)
409
+ continue;
410
+ const path = this.segmentTrackPaths.get(d.trackId);
411
+ if (path)
412
+ d.path = path;
413
+ }
347
414
  // boxes and polygons are both normalized 0-1, direct overlap test
348
415
  if (data.detectionZones && data.detectionZones.length > 0) {
349
416
  const zonesSet = new Set(this.activeSegment.zones ?? []);
@@ -366,33 +433,26 @@ export class DetectionEventManager {
366
433
  continue;
367
434
  if (face.identity) {
368
435
  if (!this.activeSegment.attributes.some((a) => a.type === 'face' && a.label === face.identity)) {
369
- this.activeSegment.attributes.push({ type: 'face', label: face.identity, parentTrackId: face.parentTrackId });
436
+ this.pushAttribute({ type: 'face', label: face.identity, parentTrackId: face.parentTrackId });
370
437
  }
371
438
  }
372
439
  else if (face.embedding?.length) {
373
- if (face.parentTrackId !== undefined) {
374
- const existingIdx = this.segmentFaceTrackIds.get(face.parentTrackId);
375
- if (existingIdx !== undefined) {
376
- const existing = this.activeSegment.attributes[existingIdx];
377
- if (existing && face.confidence > (existing.confidence ?? 0)) {
378
- existing.confidence = face.confidence;
379
- existing.embedding = face.embedding;
380
- existing.embeddingModel = data.faceEmbeddingModel;
381
- existing.thumbnail = face.thumbnail;
382
- }
383
- continue;
440
+ // one slot per person, and one shared slot for faces the tracker could
441
+ // not attach to anyone: without a track there is nothing to tell two
442
+ // strangers apart by, and a slot per sighting would file the same face
443
+ // into the index on every tick
444
+ const bucket = face.parentTrackId !== undefined ? `t${face.parentTrackId}` : 'untracked';
445
+ const existingIdx = this.segmentFaceTrackIds.get(bucket);
446
+ if (existingIdx !== undefined) {
447
+ const existing = this.activeSegment.attributes[existingIdx];
448
+ if (existing && face.confidence > (existing.confidence ?? 0)) {
449
+ existing.confidence = face.confidence;
450
+ this.heldAttributes[existingIdx] = { thumbnail: face.thumbnail, embedding: face.embedding, embeddingModel: data.faceEmbeddingModel };
384
451
  }
385
- this.segmentFaceTrackIds.set(face.parentTrackId, this.activeSegment.attributes.length);
452
+ continue;
386
453
  }
387
- this.activeSegment.attributes.push({
388
- type: 'face',
389
- label: 'unknown',
390
- confidence: face.confidence,
391
- embedding: face.embedding,
392
- embeddingModel: data.faceEmbeddingModel,
393
- thumbnail: face.thumbnail,
394
- parentTrackId: face.parentTrackId,
395
- });
454
+ this.segmentFaceTrackIds.set(bucket, this.activeSegment.attributes.length);
455
+ this.pushAttribute({ type: 'face', label: 'unknown', confidence: face.confidence, parentTrackId: face.parentTrackId }, { thumbnail: face.thumbnail, embedding: face.embedding, embeddingModel: data.faceEmbeddingModel });
396
456
  }
397
457
  }
398
458
  this.plateVotingActive = data.plateVoting !== false;
@@ -408,7 +468,7 @@ export class DetectionEventManager {
408
468
  existing.confidence = plate.confidence;
409
469
  }
410
470
  else {
411
- this.activeSegment.attributes.push({ type: 'license_plate', label, confidence: plate.confidence, parentTrackId: plate.parentTrackId });
471
+ this.pushAttribute({ type: 'license_plate', label, confidence: plate.confidence, parentTrackId: plate.parentTrackId });
412
472
  }
413
473
  continue;
414
474
  }
@@ -456,24 +516,28 @@ export class DetectionEventManager {
456
516
  else if (this.activeSegment.attributes.some((a) => a.type === cls.attribute && a.label === cls.subAttribute)) {
457
517
  continue;
458
518
  }
459
- this.activeSegment.attributes.push({ type: cls.attribute, label: cls.subAttribute, confidence: cls.confidence, parentTrackId: cls.parentTrackId });
519
+ this.pushAttribute({ type: cls.attribute, label: cls.subAttribute, confidence: cls.confidence, parentTrackId: cls.parentTrackId });
460
520
  }
461
521
  for (const clip of data.clips) {
462
522
  if (clip.embedding?.length) {
463
- const clipKey = clip.parentTrackId !== undefined ? `${clip.parentTrackId}:${clip.label}` : clip.label;
464
- if (this.segmentClipTrackIds.has(clipKey))
523
+ // one embedding per subject actually present, not per track: a
524
+ // re-numbered track is the same person and would otherwise land in the
525
+ // search index again, while two real people must keep both appearances
526
+ const stored = this.segmentClipLabels.get(clip.label) ?? 0;
527
+ const present = this.activeSegment.detections.find((d) => d.label === clip.label)?.maxCount ?? 1;
528
+ if (stored >= Math.max(1, present))
465
529
  continue;
466
- this.segmentClipTrackIds.add(clipKey);
467
- this.activeSegment.attributes.push({
468
- type: 'clip',
469
- label: clip.label,
470
- clipEmbedding: clip.embedding,
471
- clipEmbeddingModel: data.clipEmbeddingModel,
472
- parentTrackId: clip.parentTrackId,
473
- });
530
+ this.segmentClipLabels.set(clip.label, stored + 1);
531
+ this.pushAttribute({ type: 'clip', label: clip.label, parentTrackId: clip.parentTrackId }, { clipEmbedding: clip.embedding, clipEmbeddingModel: data.clipEmbeddingModel });
474
532
  }
475
533
  }
476
534
  }
535
+ pushAttribute(attribute, held) {
536
+ if (!this.activeSegment)
537
+ return;
538
+ this.activeSegment.attributes.push(attribute);
539
+ this.heldAttributes[this.activeSegment.attributes.length - 1] = held ?? {};
540
+ }
477
541
  extractTriggers(data, now) {
478
542
  const triggers = [];
479
543
  if (data.motion?.detected) {
@@ -517,7 +581,7 @@ export class DetectionEventManager {
517
581
  updateTypes() {
518
582
  if (!this.activeEvent)
519
583
  return;
520
- const types = new Set();
584
+ const types = new Set(this.activeEvent.types);
521
585
  for (const t of this.activeEvent.triggers)
522
586
  types.add(t.type);
523
587
  // activeEvent.segments is only filled during publishSegment, include the
@@ -526,57 +590,26 @@ export class DetectionEventManager {
526
590
  for (const seg of segs) {
527
591
  for (const d of seg.detections)
528
592
  types.add(d.label);
529
- for (const attr of seg.attributes)
593
+ for (const attr of seg.attributes) {
594
+ if (attr.type === CLIP_ATTRIBUTE)
595
+ continue;
530
596
  types.add(attr.type);
597
+ }
531
598
  }
532
599
  this.activeEvent.types = [...types];
533
600
  }
534
601
  hasNewDetections(data) {
535
602
  return data.objects.length > 0 || data.faces.length > 0 || data.plates.length > 0 || data.classifiers.length > 0;
536
603
  }
537
- resetSegmentTimer(timeoutSeconds) {
538
- if (this.segmentTimer)
539
- clearTimeout(this.segmentTimer);
540
- this.segmentTimer = setTimeout(() => {
541
- this.segmentTimer = null;
542
- this.closeSegment();
543
- }, timeoutSeconds * 1000);
544
- }
545
604
  updateThumbnails(thumbnails) {
546
605
  for (const thumb of thumbnails) {
547
606
  const label = thumb.label;
548
- if (label.startsWith('face:') || label.startsWith('plate:') || label.startsWith('class:')) {
549
- this.updateBestCandidate(this.attributeThumbnails, label, thumb);
550
- // a moving vehicle produces a distinct plate crop almost every frame, cap retention
551
- if (label.startsWith('plate:'))
552
- this.prunePlateThumbnails();
553
- }
554
- else {
555
- const hasAttr = thumbnails.some((t) => t.label.startsWith('face:') || t.label.startsWith('plate:') || t.label.startsWith('class:'));
556
- const candidate = {
557
- jpeg: thumb.jpeg,
558
- score: thumb.score,
559
- area: thumb.area,
560
- onEdge: thumb.onEdge,
561
- hasAttribute: hasAttr,
562
- trackId: thumb.trackId,
563
- speed: thumb.speed,
564
- };
565
- if (!this.sceneThumbnail || this.isBetterScene(candidate, this.sceneThumbnail)) {
566
- this.sceneThumbnail = candidate;
567
- }
568
- if (!this.eventBestShot || this.isBetterScene(candidate, this.eventBestShot)) {
569
- this.eventBestShot = candidate;
570
- if (this.eventBestShotPushed) {
571
- this.eventBestShotDirty = true;
572
- }
573
- else {
574
- this.eventBestShotPushed = true;
575
- this.publishEventThumbnail(candidate.jpeg, 'best-shot');
576
- }
577
- }
578
- this.updateBestCandidate(this.detectionLabelThumbnails, label, thumb);
579
- }
607
+ if (!label.startsWith('face:') && !label.startsWith('plate:') && !label.startsWith('class:'))
608
+ continue;
609
+ this.updateBestCandidate(this.attributeThumbnails, label, thumb);
610
+ // a moving vehicle produces a distinct plate crop almost every frame, cap retention
611
+ if (label.startsWith('plate:'))
612
+ this.prunePlateThumbnails();
580
613
  }
581
614
  }
582
615
  prunePlateThumbnails() {
@@ -605,7 +638,6 @@ export class DetectionEventManager {
605
638
  }
606
639
  const cm = DetectionEventManager.isMoving(candidate);
607
640
  const currM = DetectionEventManager.isMoving(current);
608
- // prefer moving objects over stationary
609
641
  if (cm && !currM) {
610
642
  this.logger.trace(`Thumbnail ${key}: prefer moving track#${candidate.trackId} (speed=${candidate.speed?.toFixed(4)}) over static track#${current.trackId}`);
611
643
  map.set(key, candidate);
@@ -617,109 +649,165 @@ export class DetectionEventManager {
617
649
  map.set(key, candidate);
618
650
  }
619
651
  }
620
- isBetterScene(candidate, current) {
621
- if (candidate.hasAttribute && !current.hasAttribute)
622
- return true;
623
- const cm = DetectionEventManager.isMoving(candidate);
624
- const currM = DetectionEventManager.isMoving(current);
625
- if (cm && !currM) {
626
- this.logger.trace(`Scene thumbnail: prefer moving track#${candidate.trackId} (speed=${candidate.speed?.toFixed(4)}) over static track#${current.trackId}`);
627
- return true;
628
- }
629
- if (!cm && currM)
630
- return false;
631
- if (candidate.onEdge && !current.onEdge)
632
- return false;
633
- if (candidate.score > current.score * 1.05)
634
- return true;
635
- if (candidate.area > current.area * 1.1)
636
- return true;
637
- return false;
638
- }
639
652
  static isMoving(c) {
640
653
  return (c.speed ?? 0) >= MIN_MOVING_SPEED;
641
654
  }
642
- injectSegmentThumbnails() {
643
- if (!this.activeSegment)
644
- return;
645
- if (this.sceneThumbnail) {
646
- this.activeSegment.thumbnail = this.sceneThumbnail.jpeg;
647
- }
648
- for (const detection of this.activeSegment.detections) {
649
- const detCand = this.detectionLabelThumbnails.get(detection.label);
650
- if (!detCand)
651
- continue;
652
- if (detCand.jpeg === this.sceneThumbnail?.jpeg)
653
- continue;
654
- detection.thumbnail = detCand.jpeg;
655
- }
656
- for (const attr of this.activeSegment.attributes) {
657
- if (attr.thumbnail)
658
- continue;
659
- const keys = [`face:${attr.label}`, `plate:${attr.label}`, `class:${attr.label}`];
660
- const directKey = `${attr.type}:${attr.label}`;
661
- if (!keys.includes(directKey))
662
- keys.unshift(directKey);
663
- for (const key of keys) {
664
- const cand = this.attributeThumbnails.get(key);
665
- if (cand) {
666
- attr.thumbnail = cand.jpeg;
667
- break;
655
+ segmentAttachments(withEmbeddings) {
656
+ const attachments = {};
657
+ const moment = this.segmentMoment;
658
+ if (moment && moment.capturedAt !== this.shippedSceneAt) {
659
+ attachments.strip = moment.strip;
660
+ attachments.card = moment.card;
661
+ this.shippedSceneAt = moment.capturedAt;
662
+ }
663
+ const attributes = this.activeSegment?.attributes ?? [];
664
+ const crops = [];
665
+ let anyCrop = false;
666
+ for (const [index, attribute] of attributes.entries()) {
667
+ const held = this.heldAttributes[index];
668
+ const crop = held?.thumbnail ?? this.attributeThumbnailFor(attribute);
669
+ if (crop?.length && this.shippedAttributes.get(index) !== crop) {
670
+ this.shippedAttributes.set(index, crop);
671
+ crops.push(crop);
672
+ anyCrop = true;
673
+ }
674
+ else {
675
+ crops.push(undefined);
676
+ }
677
+ // embeddings are write-only into the face and clip indexes, and the
678
+ // recorder reads them once when the segment closes
679
+ if (withEmbeddings && held) {
680
+ if (held.embedding) {
681
+ attribute.embedding = held.embedding;
682
+ attribute.embeddingModel = held.embeddingModel;
683
+ }
684
+ if (held.clipEmbedding) {
685
+ attribute.clipEmbedding = held.clipEmbedding;
686
+ attribute.clipEmbeddingModel = held.clipEmbeddingModel;
668
687
  }
669
688
  }
670
689
  }
690
+ if (anyCrop)
691
+ attachments.attributes = crops;
692
+ return attachments;
693
+ }
694
+ attributeThumbnailFor(attribute) {
695
+ const keys = [`face:${attribute.label}`, `plate:${attribute.label}`, `class:${attribute.label}`];
696
+ const directKey = `${attribute.type}:${attribute.label}`;
697
+ if (!keys.includes(directKey))
698
+ keys.unshift(directKey);
699
+ for (const key of keys) {
700
+ const candidate = this.attributeThumbnails.get(key);
701
+ if (candidate)
702
+ return candidate.jpeg;
703
+ }
704
+ return undefined;
705
+ }
706
+ takeMoment(moment) {
707
+ if (!this.beatsMoment(moment.rank, moment.score, moment.stream, this.segmentMoment)) {
708
+ // debugging
709
+ this.recordMomentVerdict(moment, 'rejected');
710
+ return;
711
+ }
712
+ // debugging
713
+ this.recordMomentVerdict(moment, 'kept');
714
+ this.segmentMoment = moment;
671
715
  }
672
- stripSegmentThumbnails() {
673
- if (!this.activeSegment)
716
+ heldMomentInfo() {
717
+ const held = this.segmentMoment;
718
+ if (!held)
719
+ return undefined;
720
+ return { capturedAt: held.capturedAt, score: held.score, rank: held.rank, stream: held.stream };
721
+ }
722
+ incumbentMoment(at) {
723
+ if (this.activeSegment)
724
+ return this.segmentMoment;
725
+ return this.pendingMoment?.capturedAt === at ? this.pendingMoment : undefined;
726
+ }
727
+ beatsMoment(rank, score, stream, held) {
728
+ if (!held)
729
+ return true;
730
+ if (rank !== held.rank)
731
+ return rank > held.rank;
732
+ // the score is normalized, so it cannot see that a main-stream crop is the
733
+ // same framing with several times the pixels: that one only has to tie
734
+ if (stream === 'main' && held.stream === 'low')
735
+ return score > held.score;
736
+ return score > held.score * MOMENT_IMPROVEMENT;
737
+ }
738
+ // debugging
739
+ recordMomentVerdict(moment, verdict) {
740
+ if (!detectionRecord.active)
674
741
  return;
675
- this.activeSegment.thumbnail = undefined;
676
- for (const det of this.activeSegment.detections)
677
- det.thumbnail = undefined;
678
- for (const attr of this.activeSegment.attributes)
679
- attr.thumbnail = undefined;
742
+ detectionRecord.momentVerdict({
743
+ verdict,
744
+ capturedAt: moment.capturedAt,
745
+ score: moment.score,
746
+ rank: moment.rank,
747
+ stream: moment.stream,
748
+ held: this.heldMomentInfo(),
749
+ eventId: this.activeEvent?.id.slice(0, 8),
750
+ segment: this.activeSegment ? this.segmentIndex : undefined,
751
+ });
680
752
  }
681
753
  clearSegmentThumbnails() {
682
- this.sceneThumbnail = null;
683
- this.sceneThumbnailShipped = false;
684
- this.detectionLabelThumbnails.clear();
754
+ this.shippedSceneAt = 0;
755
+ this.segmentMoment = undefined;
756
+ this.pendingMoment = undefined;
685
757
  this.attributeThumbnails.clear();
758
+ this.heldAttributes = [];
759
+ this.shippedAttributes.clear();
686
760
  this.segmentFaceTrackIds.clear();
687
761
  this.segmentPlateAttrIndex.clear();
688
762
  this.segmentPlateReads.clear();
689
763
  this.segmentClassifierTrackIds.clear();
690
- this.segmentClipTrackIds.clear();
764
+ this.segmentClipLabels.clear();
691
765
  }
692
- publish(type) {
766
+ publish(type, attachments) {
693
767
  if (!this.activeEvent)
694
768
  return;
695
- this.proxy.publish(this.eventSubject, { type, data: this.activeEvent });
769
+ const message = { type, data: leanEvent(this.activeEvent) };
770
+ this.proxy.publish(this.eventSubject, message);
771
+ this.nvr.send(type, this.activeEvent, attachments);
772
+ // debugging
773
+ this.recordMessage(type, attachments);
696
774
  this.lastPublishTime = Date.now();
697
775
  }
776
+ // debugging
777
+ recordMessage(type, attachments) {
778
+ if (!detectionRecord.active || !this.activeEvent)
779
+ return;
780
+ const at = this.segmentMoment?.capturedAt ?? this.activeEvent.lastUpdate;
781
+ const segment = this.activeSegment;
782
+ const attributes = segment?.attributes ?? [];
783
+ detectionRecord.message({
784
+ type,
785
+ eventId: this.activeEvent.id.slice(0, 8),
786
+ segment: segment ? this.segmentIndex : undefined,
787
+ types: this.activeEvent.types,
788
+ recorderReachable: this.nvr.connected,
789
+ detections: segment?.detections.map((d) => ({ label: d.label, score: d.score, count: d.maxCount, track: d.trackId, moving: d.moving })),
790
+ attributes: attributes.map((a) => ({ type: a.type, label: a.label, confidence: a.confidence, parent: a.parentTrackId })),
791
+ sent: {
792
+ scene: attachments?.scene ? detectionRecord.picture(this.eventThumbnailAt || at, 'scene', 'event', attachments.scene) : undefined,
793
+ strip: attachments?.strip ? detectionRecord.picture(at, 'moment', 'strip', attachments.strip) : undefined,
794
+ card: attachments?.card ? detectionRecord.picture(at, 'moment', 'card', attachments.card) : undefined,
795
+ attributes: attachments?.attributes?.map((crop, index) => crop ? detectionRecord.picture(at, 'attr', `${attributes[index]?.type}-${attributes[index]?.label}`, crop) : undefined),
796
+ },
797
+ momentStream: this.segmentMoment?.stream,
798
+ momentAt: this.segmentMoment?.capturedAt,
799
+ });
800
+ }
698
801
  publishSegment(type) {
699
802
  if (!this.activeEvent || !this.activeSegment)
700
803
  return;
701
804
  this.activeEvent.segments = [this.activeSegment];
702
805
  this.activeEvent.segmentIndex = this.segmentIndex;
703
806
  this.logSegment(type);
704
- if (type === 'segment-end') {
705
- this.injectSegmentThumbnails();
706
- this.publish(type);
707
- }
708
- else if (type === 'segment-start') {
709
- this.injectSegmentThumbnails();
710
- this.publish(type);
711
- this.sceneThumbnailShipped = this.sceneThumbnail !== null;
712
- this.stripSegmentThumbnails();
713
- }
714
- else if (!this.sceneThumbnailShipped && this.sceneThumbnail) {
715
- this.activeSegment.thumbnail = this.sceneThumbnail.jpeg;
716
- this.publish(type);
717
- this.activeSegment.thumbnail = undefined;
718
- this.sceneThumbnailShipped = true;
719
- }
720
- else {
721
- this.publish(type);
722
- }
807
+ const moment = this.segmentMoment;
808
+ if (moment)
809
+ this.activeSegment.thumbnailAt = moment.capturedAt;
810
+ this.publish(type, this.segmentAttachments(type === 'segment-end'));
723
811
  }
724
812
  publishSegmentThrottled(type) {
725
813
  const now = Date.now();
@@ -749,17 +837,16 @@ export class DetectionEventManager {
749
837
  }
750
838
  if (seg.attributes.length > 0) {
751
839
  const groups = new Map();
752
- for (const a of seg.attributes) {
840
+ for (const [index, a] of seg.attributes.entries()) {
841
+ const held = this.heldAttributes[index];
753
842
  const list = groups.get(a.type) ?? [];
754
843
  let info = a.label;
755
844
  if (a.confidence)
756
845
  info += `(${a.confidence.toFixed(2)})`;
757
- if (a.type === 'face' && a.embedding?.length)
846
+ if (held?.embedding?.length || held?.clipEmbedding?.length)
758
847
  info += '+emb';
759
- if (a.type === 'face' && a.thumbnail)
848
+ if (held?.thumbnail ?? this.attributeThumbnailFor(a))
760
849
  info += '+thumb';
761
- if (a.type === 'clip' && a.clipEmbedding?.length)
762
- info += '+emb';
763
850
  list.push(info);
764
851
  groups.set(a.type, list);
765
852
  }
@@ -782,10 +869,10 @@ export class DetectionEventManager {
782
869
  parts.push(`zones=[${seg.zones.join(',')}]`);
783
870
  }
784
871
  const thumbParts = [];
785
- if (this.sceneThumbnail)
786
- thumbParts.push(`scene:${jpegInfo(this.sceneThumbnail.jpeg)}`);
787
- for (const [label, cand] of this.detectionLabelThumbnails) {
788
- thumbParts.push(cand.jpeg === this.sceneThumbnail?.jpeg ? `${label}:=scene` : `${label}:${jpegInfo(cand.jpeg)}`);
872
+ const moment = this.segmentMoment;
873
+ if (moment) {
874
+ const shows = moment.rank >= MOMENT_RANK_ATTRIBUTE ? 'attr' : 'obj';
875
+ thumbParts.push(`moment(${shows},${moment.stream}):${jpegInfo(moment.strip)}${moment.card ? `+card:${jpegInfo(moment.card)}` : ''}`);
789
876
  }
790
877
  for (const [label, cand] of this.attributeThumbnails)
791
878
  thumbParts.push(`${label}:${jpegInfo(cand.jpeg)}`);