@camera.ui/server 2.0.10 → 2.0.12

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 (381) hide show
  1. package/dist/interface/assets/{404-ChR2IVti.js → 404-Dfyzm8bF.js} +1 -1
  2. package/dist/interface/assets/{About-CDQ55crC.js → About-B4Y3WP7T.js} +1 -1
  3. package/dist/interface/assets/{Adminpanel-CiJGwx7_.js → Adminpanel-DSk1uh2x.js} +1 -1
  4. package/dist/interface/assets/Automation-CTSfLcmF.js +2 -0
  5. package/dist/interface/assets/AutomationImport-B1P0T0Pe.js +2 -0
  6. package/dist/interface/assets/AutomationStore-ZaaXPPbd.js +2 -0
  7. package/dist/interface/assets/AutomationStoreDetail-B2vc7mTZ.js +2 -0
  8. package/dist/interface/assets/Automations-Bvw-jTKi.js +2 -0
  9. package/dist/interface/assets/Camera-BxmJXk11.js +2 -0
  10. package/dist/interface/assets/{CameraConsole-dx9vB5ht.js → CameraConsole-CVqgED5u.js} +2 -2
  11. package/dist/interface/assets/Cameras-DT62fcZK.js +652 -0
  12. package/dist/interface/assets/Camview-CqSckgLr.js +1 -0
  13. package/dist/interface/assets/Config-p9t9zgly.js +2 -0
  14. package/dist/interface/assets/{ConfigActionCameraControl-CrWmGvdE.js → ConfigActionCameraControl-BLROOU0q.js} +1 -1
  15. package/dist/interface/assets/{ConfigActionDelay-1kd69ysm.js → ConfigActionDelay-q0pOTOzh.js} +1 -1
  16. package/dist/interface/assets/{ConfigActionHttp-XY-r_hEX.js → ConfigActionHttp-DiMXKRGz.js} +1 -1
  17. package/dist/interface/assets/ConfigActionImageInput-u5xX9t3-.js +1 -0
  18. package/dist/interface/assets/{ConfigActionMqtt-DsX-q9M_.js → ConfigActionMqtt-BkZl3uYq.js} +1 -1
  19. package/dist/interface/assets/ConfigActionNotification-DIkFNlKe.js +1 -0
  20. package/dist/interface/assets/{ConfigActionOutput-DMYPThT1.js → ConfigActionOutput-CJF0F4cT.js} +1 -1
  21. package/dist/interface/assets/{ConfigActionPlugin-rCaB0HjK.js → ConfigActionPlugin-rQeJ4umG.js} +1 -1
  22. package/dist/interface/assets/ConfigActionSensor-BWHpkoMs.js +1 -0
  23. package/dist/interface/assets/{ConfigActionSnapshot-8vrwtN10.js → ConfigActionSnapshot-BlvQZl1R.js} +1 -1
  24. package/dist/interface/assets/{ConfigActionVariable-Dy8ZnhCO.js → ConfigActionVariable-BMV-BDAk.js} +1 -1
  25. package/dist/interface/assets/{ConfigConditionIfElse-DK9Z6-kN.js → ConfigConditionIfElse-C5geCT1S.js} +1 -1
  26. package/dist/interface/assets/ConfigConditionSensorState-8bIGEhQd.js +1 -0
  27. package/dist/interface/assets/{ConfigConditionSwitch-_Gxu6OYc.js → ConfigConditionSwitch-PwrCSnTQ.js} +1 -1
  28. package/dist/interface/assets/{ConfigConditionTime-Ce8AortY.js → ConfigConditionTime-DUt_dsr9.js} +1 -1
  29. package/dist/interface/assets/{ConfigSensorValueInput-BIiQ8NN6.js → ConfigSensorValueInput-CgZWxOMu.js} +1 -1
  30. package/dist/interface/assets/{ConfigTriggerDetection-CCCi-Tof.js → ConfigTriggerDetection-D4UitpXI.js} +1 -1
  31. package/dist/interface/assets/ConfigTriggerGeofence-Ci-gkmjS.js +1 -0
  32. package/dist/interface/assets/{ConfigTriggerManual-DZPdLXoe.js → ConfigTriggerManual-_PAVLJxz.js} +1 -1
  33. package/dist/interface/assets/{ConfigTriggerMqtt-4Gp-qhCg.js → ConfigTriggerMqtt-BtfXQ_Bh.js} +1 -1
  34. package/dist/interface/assets/{ConfigTriggerSchedule-DQX6czW4.js → ConfigTriggerSchedule-CHyW4YQ1.js} +1 -1
  35. package/dist/interface/assets/{ConfigTriggerSensor-CLnC2yvE.js → ConfigTriggerSensor-CZMplCYs.js} +1 -1
  36. package/dist/interface/assets/{ConfigTriggerSystem-Gae5o59O.js → ConfigTriggerSystem-OOffe8rK.js} +1 -1
  37. package/dist/interface/assets/ConfigTriggerWebhook-Baul6M1Y.js +1 -0
  38. package/dist/interface/assets/Console-MXiL0z_X.js +1 -0
  39. package/dist/interface/assets/{CuiActionButton-BAlSwXzv.js → CuiActionButton-WFz5I80P.js} +1 -1
  40. package/dist/interface/assets/{CuiAvatar-DeBKq6dT.js → CuiAvatar-BUwQnIaI.js} +1 -1
  41. package/dist/interface/assets/{CuiBBoxPlayground-yYOBCXTq.js → CuiBBoxPlayground-J7_8dCvo.js} +1 -1
  42. package/dist/interface/assets/CuiBottomSheet-BA-u9UtN.js +1 -0
  43. package/dist/interface/assets/{CuiBottomSheet-udULz0wI.js → CuiBottomSheet-CzG0n4Oa.js} +1 -1
  44. package/dist/interface/assets/CuiCameraCard-GH-DR5_s.js +1 -0
  45. package/dist/interface/assets/{CuiCameraPipCard-BxbUK-93.js → CuiCameraPipCard-CL_wj05b.js} +1 -1
  46. package/dist/interface/assets/CuiCameraRecordings-BjErk9Gl.js +1 -0
  47. package/dist/interface/assets/CuiCameraShares-qrJhZMEt.js +1 -0
  48. package/dist/interface/assets/CuiCameraSnapshot-Dn1QSGrr.js +1 -0
  49. package/dist/interface/assets/CuiCameraTable-or8VpE34.js +2 -0
  50. package/dist/interface/assets/{CuiDataTable-CB7aMmp9.js → CuiDataTable-CjXiUFiJ.js} +1 -1
  51. package/dist/interface/assets/CuiFloatingButton-BjpU1EHv.js +1 -0
  52. package/dist/interface/assets/CuiImage-BM4g6edi.css +1 -0
  53. package/dist/interface/assets/CuiImage-Bq3bxOOL.js +1 -0
  54. package/dist/interface/assets/CuiMenu-DtnIPhcr.js +1 -0
  55. package/dist/interface/assets/CuiPluginCard-DKNWUFpR.js +2 -0
  56. package/dist/interface/assets/{CuiPluginCategoryChip-yMnZpSGr.js → CuiPluginCategoryChip-cmfKx-dU.js} +1 -1
  57. package/dist/interface/assets/CuiPluginOAuthButton-C6FQiVkt.js +2 -0
  58. package/dist/interface/assets/CuiPluginTrustBadge-PVZMP1rI.js +1 -0
  59. package/dist/interface/assets/{CuiQRCode-D9QNUEmx.js → CuiQRCode-uQygC1dP.js} +1 -1
  60. package/dist/interface/assets/CuiRecordingsGrid-Cuwd4L67.js +1 -0
  61. package/dist/interface/assets/CuiSchema-CH0GXMWV.js +1 -0
  62. package/dist/interface/assets/{CuiTopNavbarItem--MOi9UUw.js → CuiTopNavbarItem-nGcC2em4.js} +1 -1
  63. package/dist/interface/assets/{CuiTopbarSlot-Bcw46PzA.js → CuiTopbarSlot-B6UMqYZl.js} +1 -1
  64. package/dist/interface/assets/Faces-cpO5vJbp.js +1 -0
  65. package/dist/interface/assets/FirstSteps-BHTcbs9O.js +1 -0
  66. package/dist/interface/assets/Instances-BXiVG2Dm.js +1 -0
  67. package/dist/interface/assets/Logs-hMg2QOGj.js +6 -0
  68. package/dist/interface/assets/{Menu-GbuCaA_6.js → Menu-BiPBCi8Z.js} +1 -1
  69. package/dist/interface/assets/OAuthDeviceFlow-Bia9UA3I.js +1 -0
  70. package/dist/interface/assets/Plugin-DfRaHAsi.js +1 -0
  71. package/dist/interface/assets/{PluginConsole-CLGkDl1F.js → PluginConsole-CRw4zTRM.js} +2 -2
  72. package/dist/interface/assets/PluginDetail-BYqji8yN.css +1 -0
  73. package/dist/interface/assets/PluginDetail-BqRoLZc7.js +2 -0
  74. package/dist/interface/assets/{PluginSchema-Dy9kDPML.js → PluginSchema-TtBJPR_R.js} +1 -1
  75. package/dist/interface/assets/PluginSearch-B_NYpJi3.js +2 -0
  76. package/dist/interface/assets/{PluginSearch-NuKgD1r3.css → PluginSearch-Bbp8D7BJ.css} +1 -1
  77. package/dist/interface/assets/PluginSearch-DnJgg6-6.js +1 -0
  78. package/dist/interface/assets/Plugins-DVFEGtj3.js +1 -0
  79. package/dist/interface/assets/Recordings-dwm6lAoJ.js +1 -0
  80. package/dist/interface/assets/{Settings-is528I5i2.js → Settings-BpBmrGpS.js} +1 -1
  81. package/dist/interface/assets/SettingsAccount-8Kh1uQqn.js +1 -0
  82. package/dist/interface/assets/{SettingsAccount-Y7hpH8Y3.css → SettingsAccount-CBJ_h7eM.css} +1 -1
  83. package/dist/interface/assets/SettingsAccount-CjgYe5mF.js +1 -0
  84. package/dist/interface/assets/SettingsAppearance-3i3Ix7j-.js +1 -0
  85. package/dist/interface/assets/{SettingsAppearance-CGaG9lml.js → SettingsAppearance-EoBxclgt.js} +1 -1
  86. package/dist/interface/assets/SettingsBackup-Bpsbg6Pm.js +1 -0
  87. package/dist/interface/assets/SettingsMqtt-ZQolc9lR.js +1 -0
  88. package/dist/interface/assets/SettingsNotifications-BOoMt1Er.js +2 -0
  89. package/dist/interface/assets/SettingsRecordings-BQhxLCgM.js +1 -0
  90. package/dist/interface/assets/SettingsRemote-Cvcmpdgb.js +1 -0
  91. package/dist/interface/assets/SettingsRemote-DYld6-1F.css +1 -0
  92. package/dist/interface/assets/SettingsSystem-B-yhq40t.js +2 -0
  93. package/dist/interface/assets/SettingsUsers-CezygBk8.js +1 -0
  94. package/dist/interface/assets/Terminal-CDQJGwb_.js +4 -0
  95. package/dist/interface/assets/{VariableInput-DW39Zo4d.js → VariableInput-CnmqCHf7.js} +1 -1
  96. package/dist/interface/assets/{VariableSuggestions-DwhFBKzJ.js → VariableSuggestions-D6IlwBqV.js} +1 -1
  97. package/dist/interface/assets/VersionsHandler-BHR1k9zz.js +7 -0
  98. package/dist/interface/assets/Workers-Bv-bWBC-.js +2 -0
  99. package/dist/interface/assets/{Workers-E6LM_yAl.css → Workers-DmcQx0L8.css} +1 -1
  100. package/dist/interface/assets/{api-Br3Jmdj6.js → api-BhOwzvxK.js} +1 -1
  101. package/dist/interface/assets/api-Cea16mc8.js +2 -0
  102. package/dist/interface/assets/api-GMfqGYqQ.css +2 -0
  103. package/dist/interface/assets/auth-CNPkdTXX.js +1 -0
  104. package/dist/interface/assets/{automations-Dd-6vvka.js → automations-CHengR-B.js} +1 -1
  105. package/dist/interface/assets/automations-DhLADBhd.js +1 -0
  106. package/dist/interface/assets/bell-outline-CHhIZudN.js +1 -0
  107. package/dist/interface/assets/{cameras-DCMMwuui.js → cameras-DyF2T0be.js} +1 -1
  108. package/dist/interface/assets/{cameras.schema-99F6GE0u.js → cameras.schema-DBzgU4m6.js} +1 -1
  109. package/dist/interface/assets/cloudHandoff-LxdvSi1a.js +1 -0
  110. package/dist/interface/assets/{config-BiEjYldh.js → config-c7o4sJrQ.js} +1 -1
  111. package/dist/interface/assets/{circular-connection-Fq-Vqe3X.js → delete-outline-CbGU9XWz.js} +1 -1
  112. package/dist/interface/assets/{deviceId-sq3mLBKa.js → deviceId-BYu9Q8Ay.js} +1 -1
  113. package/dist/interface/assets/{hasPermission-Dm18Z17u.js → hasPermission-CgyWyOhQ.js} +1 -1
  114. package/dist/interface/assets/instances-CRYtaTQS.js +1 -0
  115. package/dist/interface/assets/main-CgXkx5UO.js +3 -0
  116. package/dist/interface/assets/nodeDefinitions-DUlwYSC1.js +1 -0
  117. package/dist/interface/assets/{notifications-D87Lhlir.js → notifications-sejZCb0L.js} +1 -1
  118. package/dist/interface/assets/plugins-CCLFcD4c.js +1 -0
  119. package/dist/interface/assets/round-restart-alt-PDSZur-0.js +1 -0
  120. package/dist/interface/assets/{router-qrIK2v9X.css → router-C7b6u3Zu.css} +1 -1
  121. package/dist/interface/assets/router-DkMUvvnP.js +2 -0
  122. package/dist/interface/assets/{routerState-B08WcvfU.js → routerState-BR88YV1H.js} +1 -1
  123. package/dist/interface/assets/{server-D7bl4wSy.js → server-C7SETTy9.js} +1 -1
  124. package/dist/interface/assets/shares-Cy1SLL98.js +1 -0
  125. package/dist/interface/assets/{theme-BG6n3TRA.js → theme-DqbhRu7y.js} +1 -1
  126. package/dist/interface/assets/transit-connection-variant-DfztpRMW.js +1 -0
  127. package/dist/interface/assets/types-v8L66UlA.js +1 -0
  128. package/dist/interface/assets/{ui-Cv0M3koY.js → ui-g5rCwxUE.js} +1 -1
  129. package/dist/interface/assets/{useAppVersion-DCmhFeIs.js → useAppVersion-WfdoG9Ji.js} +1 -1
  130. package/dist/interface/assets/useBackupRestore-ootsFhdF.js +1 -0
  131. package/dist/interface/assets/{useBiometricCredentials-Tq1nEG8V.js → useBiometricCredentials-Ca75xEru.js} +1 -1
  132. package/dist/interface/assets/useCameraOptions-BpL2zbfV.js +1 -0
  133. package/dist/interface/assets/{useCuiCameraDrawer-BcAYizqy.js → useCuiCameraDrawer-BHUHw6W6.js} +1 -1
  134. package/dist/interface/assets/useCuiDialog-yVh5UWKF.js +2 -0
  135. package/dist/interface/assets/{useFileDownload-C5quSdZR.js → useFileDownload-BcaNWndS.js} +1 -1
  136. package/dist/interface/assets/useLogsSocket-BRSsUNqv.js +5 -0
  137. package/dist/interface/assets/useLogsSocket-CoA-Nq-_.css +1 -0
  138. package/dist/interface/assets/{useServerRestart-DnT0ZOYm.js → useServerRestart-PZhND5H_.js} +1 -1
  139. package/dist/interface/assets/{useSharedComposables-ffwWlpSL.js → useSharedComposables-USqd05AG.js} +1 -1
  140. package/dist/interface/assets/{useStreamStatus-CD18kTqt.js → useStreamStatus-nCx5ux1-.js} +1 -1
  141. package/dist/interface/assets/{useUpdateChannel-DbBXpySY.js → useUpdateChannel-3eHk3KXZ.js} +1 -1
  142. package/dist/interface/assets/{useUserOptions-Bb0ACtxn.js → useUserOptions-DVC4k8Zs.js} +1 -1
  143. package/dist/interface/assets/{users.schema-BGeyXreN.js → users.schema-B4fEuoKZ.js} +1 -1
  144. package/dist/interface/assets/vendor-cameraui-QuTJKoXE.js +2039 -0
  145. package/dist/interface/assets/vendor-core-CCcu_nmz.js +1 -0
  146. package/dist/interface/assets/{vendor-primevue-DB14kOh6.js → vendor-primevue-BdB7McKg.js} +84 -145
  147. package/dist/interface/assets/view-grid-BWJS0bBD.js +1 -0
  148. package/dist/interface/index.html +49 -48
  149. package/dist/interface/sw.js +1 -1
  150. package/dist/server/package.json +10 -10
  151. package/dist/server/requirements.txt +1 -1
  152. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/__init__.py +2 -0
  153. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/camera/detection.py +3 -0
  154. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/__init__.py +2 -0
  155. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/base.py +10 -2
  156. package/dist/server/src/_camera_ui_tools/camera_ui_sdk/sensor/ptz.py +45 -2
  157. package/dist/server/src/api/controllers/instances.controller.d.ts +2 -2
  158. package/dist/server/src/api/controllers/instances.controller.js +7 -7
  159. package/dist/server/src/api/controllers/instances.controller.js.map +1 -1
  160. package/dist/server/src/api/controllers/plugins.controller.js +1 -1
  161. package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
  162. package/dist/server/src/api/database/backfill.d.ts +5 -0
  163. package/dist/server/src/api/database/backfill.js +89 -0
  164. package/dist/server/src/api/database/backfill.js.map +1 -0
  165. package/dist/server/src/api/database/index.d.ts +1 -0
  166. package/dist/server/src/api/database/index.js +29 -43
  167. package/dist/server/src/api/database/index.js.map +1 -1
  168. package/dist/server/src/api/database/record-schemas.d.ts +231 -0
  169. package/dist/server/src/api/database/record-schemas.js +194 -0
  170. package/dist/server/src/api/database/record-schemas.js.map +1 -0
  171. package/dist/server/src/api/database/types.d.ts +8 -0
  172. package/dist/server/src/api/routes/instances.routes.js +2 -1
  173. package/dist/server/src/api/routes/instances.routes.js.map +1 -1
  174. package/dist/server/src/api/schemas/cameras.schema.d.ts +265 -1
  175. package/dist/server/src/api/schemas/cameras.schema.js +10 -0
  176. package/dist/server/src/api/schemas/cameras.schema.js.map +1 -1
  177. package/dist/server/src/api/schemas/config.schema.d.ts +2 -0
  178. package/dist/server/src/api/schemas/config.schema.js +1 -0
  179. package/dist/server/src/api/schemas/config.schema.js.map +1 -1
  180. package/dist/server/src/api/schemas/instances.schema.d.ts +4 -0
  181. package/dist/server/src/api/schemas/instances.schema.js +5 -0
  182. package/dist/server/src/api/schemas/instances.schema.js.map +1 -1
  183. package/dist/server/src/api/schemas/remote.schema.d.ts +1 -1
  184. package/dist/server/src/api/services/backupScheduler.service.js +1 -1
  185. package/dist/server/src/api/services/backupScheduler.service.js.map +1 -1
  186. package/dist/server/src/api/services/cameras.service.d.ts +1 -0
  187. package/dist/server/src/api/services/cameras.service.js +18 -1
  188. package/dist/server/src/api/services/cameras.service.js.map +1 -1
  189. package/dist/server/src/api/services/instances.service.d.ts +12 -3
  190. package/dist/server/src/api/services/instances.service.js +123 -36
  191. package/dist/server/src/api/services/instances.service.js.map +1 -1
  192. package/dist/server/src/api/services/plugins.service.js +29 -6
  193. package/dist/server/src/api/services/plugins.service.js.map +1 -1
  194. package/dist/server/src/api/services/virtualsensors.service.js +2 -2
  195. package/dist/server/src/api/services/virtualsensors.service.js.map +1 -1
  196. package/dist/server/src/api/types/index.d.ts +4 -1
  197. package/dist/server/src/api/websocket/nsp/main.js +3 -0
  198. package/dist/server/src/api/websocket/nsp/main.js.map +1 -1
  199. package/dist/server/src/api/websocket/nsp/server.d.ts +1 -0
  200. package/dist/server/src/api/websocket/nsp/server.js +3 -1
  201. package/dist/server/src/api/websocket/nsp/server.js.map +1 -1
  202. package/dist/server/src/camera/controller.d.ts +2 -1
  203. package/dist/server/src/camera/controller.js +19 -16
  204. package/dist/server/src/camera/controller.js.map +1 -1
  205. package/dist/server/src/camera/decoder/audio-loop.d.ts +25 -0
  206. package/dist/server/src/camera/decoder/audio-loop.js +163 -0
  207. package/dist/server/src/camera/decoder/audio-loop.js.map +1 -0
  208. package/dist/server/src/camera/decoder/cascade-manager.js +1 -4
  209. package/dist/server/src/camera/decoder/cascade-manager.js.map +1 -1
  210. package/dist/server/src/camera/decoder/detection-coordinator.d.ts +37 -97
  211. package/dist/server/src/camera/decoder/detection-coordinator.js +492 -1369
  212. package/dist/server/src/camera/decoder/detection-coordinator.js.map +1 -1
  213. package/dist/server/src/camera/decoder/detection-pipeline.d.ts +4 -0
  214. package/dist/server/src/camera/decoder/detection-pipeline.js +14 -24
  215. package/dist/server/src/camera/decoder/detection-pipeline.js.map +1 -1
  216. package/dist/server/src/camera/decoder/dwell-manager.js +1 -1
  217. package/dist/server/src/camera/decoder/dwell-manager.js.map +1 -1
  218. package/dist/server/src/camera/decoder/event-manager.js +15 -28
  219. package/dist/server/src/camera/decoder/event-manager.js.map +1 -1
  220. package/dist/server/src/camera/decoder/event-thumbnailer.d.ts +38 -0
  221. package/dist/server/src/camera/decoder/event-thumbnailer.js +192 -0
  222. package/dist/server/src/camera/decoder/event-thumbnailer.js.map +1 -0
  223. package/dist/server/src/camera/decoder/plugin-registry.d.ts +31 -0
  224. package/dist/server/src/camera/decoder/plugin-registry.js +114 -0
  225. package/dist/server/src/camera/decoder/plugin-registry.js.map +1 -0
  226. package/dist/server/src/camera/decoder/{ptz-autotracker.d.ts → ptz/autotracker.d.ts} +19 -0
  227. package/dist/server/src/camera/decoder/ptz/autotracker.js +537 -0
  228. package/dist/server/src/camera/decoder/ptz/autotracker.js.map +1 -0
  229. package/dist/server/src/camera/decoder/reconnect-backoff.d.ts +6 -0
  230. package/dist/server/src/camera/decoder/reconnect-backoff.js +17 -0
  231. package/dist/server/src/camera/decoder/reconnect-backoff.js.map +1 -0
  232. package/dist/server/src/camera/decoder/secondary-stage.d.ts +37 -0
  233. package/dist/server/src/camera/decoder/secondary-stage.js +445 -0
  234. package/dist/server/src/camera/decoder/secondary-stage.js.map +1 -0
  235. package/dist/server/src/camera/decoder/{audio-source.js → sources/audio-source.js} +2 -2
  236. package/dist/server/src/camera/decoder/sources/audio-source.js.map +1 -0
  237. package/dist/server/src/camera/decoder/{frame-source.d.ts → sources/frame-source.d.ts} +4 -0
  238. package/dist/server/src/camera/decoder/{frame-source.js → sources/frame-source.js} +30 -12
  239. package/dist/server/src/camera/decoder/sources/frame-source.js.map +1 -0
  240. package/dist/server/src/camera/decoder/{snapshot-source.d.ts → sources/snapshot-source.d.ts} +2 -5
  241. package/dist/server/src/camera/decoder/{snapshot-source.js → sources/snapshot-source.js} +11 -15
  242. package/dist/server/src/camera/decoder/sources/snapshot-source.js.map +1 -0
  243. package/dist/server/src/camera/decoder/stationary-suppressor.d.ts +21 -0
  244. package/dist/server/src/camera/decoder/stationary-suppressor.js +141 -0
  245. package/dist/server/src/camera/decoder/stationary-suppressor.js.map +1 -0
  246. package/dist/server/src/camera/decoder/types.d.ts +6 -1
  247. package/dist/server/src/camera/decoder/types.js +1 -0
  248. package/dist/server/src/camera/decoder/types.js.map +1 -1
  249. package/dist/server/src/camera/decoder/worker.d.ts +1 -0
  250. package/dist/server/src/camera/decoder/worker.js +11 -7
  251. package/dist/server/src/camera/decoder/worker.js.map +1 -1
  252. package/dist/server/src/camera/index.d.ts +5 -1
  253. package/dist/server/src/camera/index.js.map +1 -1
  254. package/dist/server/src/camera/sensors/controller.js +4 -3
  255. package/dist/server/src/camera/sensors/controller.js.map +1 -1
  256. package/dist/server/src/go2rtc/api/routes/discover.js +2 -1
  257. package/dist/server/src/go2rtc/api/routes/discover.js.map +1 -1
  258. package/dist/server/src/go2rtc/api/routes/snapshot.d.ts +3 -3
  259. package/dist/server/src/go2rtc/api/routes/snapshot.js +1 -1
  260. package/dist/server/src/go2rtc/api/routes/snapshot.js.map +1 -1
  261. package/dist/server/src/go2rtc/types.d.ts +3 -0
  262. package/dist/server/src/go2rtc/types.js.map +1 -1
  263. package/dist/server/src/main.js +26 -3
  264. package/dist/server/src/main.js.map +1 -1
  265. package/dist/server/src/manager/downloadManager.js +0 -2
  266. package/dist/server/src/manager/downloadManager.js.map +1 -1
  267. package/dist/server/src/mqtt/bridge.js +1 -1
  268. package/dist/server/src/mqtt/bridge.js.map +1 -1
  269. package/dist/server/src/plugins/schema.js +1 -1
  270. package/dist/server/src/plugins/schema.js.map +1 -1
  271. package/dist/server/src/remote/services/cloudflare-managed.js +16 -5
  272. package/dist/server/src/remote/services/cloudflare-managed.js.map +1 -1
  273. package/dist/server/src/remote/services/cloudflare.d.ts +2 -2
  274. package/dist/server/src/remote/services/cloudflare.js +16 -17
  275. package/dist/server/src/remote/services/cloudflare.js.map +1 -1
  276. package/dist/server/src/remote/services/cloudflaredBinary.d.ts +2 -0
  277. package/dist/server/src/remote/services/cloudflaredBinary.js +20 -0
  278. package/dist/server/src/remote/services/cloudflaredBinary.js.map +1 -0
  279. package/dist/server/src/remote/services/index.d.ts +1 -0
  280. package/dist/server/src/remote/services/index.js +20 -5
  281. package/dist/server/src/remote/services/index.js.map +1 -1
  282. package/dist/server/src/remote/services/urlReadiness.d.ts +11 -0
  283. package/dist/server/src/remote/services/urlReadiness.js +129 -0
  284. package/dist/server/src/remote/services/urlReadiness.js.map +1 -0
  285. package/dist/server/src/rpc/interfaces/device.d.ts +6 -0
  286. package/dist/server/src/services/config/defaults.js +1 -0
  287. package/dist/server/src/services/config/defaults.js.map +1 -1
  288. package/dist/server/src/services/config/types.d.ts +1 -0
  289. package/dist/server/src/utils/npm/index.d.ts +11 -2
  290. package/dist/server/src/utils/npm/index.js +14 -4
  291. package/dist/server/src/utils/npm/index.js.map +1 -1
  292. package/dist/server/src/utils/pythonInstaller.js +3 -3
  293. package/dist/server/src/utils/pythonInstaller.js.map +1 -1
  294. package/dist/server/src/workers/capabilities/plugin-host.js +4 -1
  295. package/dist/server/src/workers/capabilities/plugin-host.js.map +1 -1
  296. package/package.json +10 -10
  297. package/dist/interface/assets/Automation-Kt6pl4MS.js +0 -2
  298. package/dist/interface/assets/AutomationImport-DWQkfeuR.js +0 -2
  299. package/dist/interface/assets/AutomationStore-FbQdggSq.js +0 -2
  300. package/dist/interface/assets/AutomationStoreDetail-D15G_MQy.js +0 -2
  301. package/dist/interface/assets/Automations-urwh-nzl.js +0 -2
  302. package/dist/interface/assets/Camera-Brp9vdg2.js +0 -2
  303. package/dist/interface/assets/Cameras-DDut77Xv.js +0 -652
  304. package/dist/interface/assets/Camview-ChimIRuL.js +0 -1
  305. package/dist/interface/assets/Config-Cy5j6yf_.js +0 -2
  306. package/dist/interface/assets/ConfigActionImageInput-DJovQd4V.js +0 -1
  307. package/dist/interface/assets/ConfigActionNotification-BM2X-K-D.js +0 -1
  308. package/dist/interface/assets/ConfigActionSensor-gxpOX2DC.js +0 -1
  309. package/dist/interface/assets/ConfigConditionSensorState-BaFj9WYl.js +0 -1
  310. package/dist/interface/assets/ConfigTriggerGeofence-DOxaQSWM.js +0 -1
  311. package/dist/interface/assets/ConfigTriggerWebhook-Czyo2Bs-.js +0 -1
  312. package/dist/interface/assets/Console-DBJHlPg2.js +0 -1
  313. package/dist/interface/assets/CuiBottomSheet-B1jcfI0o.js +0 -1
  314. package/dist/interface/assets/CuiCameraCard-HEi3Hoe-.js +0 -1
  315. package/dist/interface/assets/CuiCameraRecordings-C5bd4VAf.js +0 -1
  316. package/dist/interface/assets/CuiCameraShares-BNjnm9yr.js +0 -1
  317. package/dist/interface/assets/CuiCameraSnapshot-C-iPOB3g.js +0 -1
  318. package/dist/interface/assets/CuiCameraTable-CDpfm8fi.js +0 -2
  319. package/dist/interface/assets/CuiFloatingButton-DdI-E8dh.js +0 -1
  320. package/dist/interface/assets/CuiImage-Bxf7z2N4.css +0 -1
  321. package/dist/interface/assets/CuiImage-DBQAYfn1.js +0 -1
  322. package/dist/interface/assets/CuiMenu--tB8FqMF.js +0 -1
  323. package/dist/interface/assets/CuiPluginCard-Cb0XSLIr.js +0 -2
  324. package/dist/interface/assets/CuiPluginOAuthButton-CuppMPTq.js +0 -2
  325. package/dist/interface/assets/CuiPluginTrustBadge-Bcnptf84.js +0 -1
  326. package/dist/interface/assets/CuiRecordingsGrid-DlKUfbeS.js +0 -1
  327. package/dist/interface/assets/CuiSchema-B6q285jE.js +0 -1
  328. package/dist/interface/assets/Faces-DtJmIku2.js +0 -1
  329. package/dist/interface/assets/FirstSteps-CsMSK_YI.js +0 -1
  330. package/dist/interface/assets/Instances-BTNzUfGz.js +0 -1
  331. package/dist/interface/assets/Logs-Bic2YIta.js +0 -6
  332. package/dist/interface/assets/OAuthDeviceFlow-DwSJHrqc.js +0 -1
  333. package/dist/interface/assets/Plugin-B8656Gzo.js +0 -1
  334. package/dist/interface/assets/PluginDetail-BsIkPUY8.css +0 -1
  335. package/dist/interface/assets/PluginDetail-DS8wUbYr.js +0 -2
  336. package/dist/interface/assets/PluginSearch-DBdp5Ifo.js +0 -1
  337. package/dist/interface/assets/PluginSearch-DFtTwd_R.js +0 -2
  338. package/dist/interface/assets/Plugins-C_kdqAp4.js +0 -1
  339. package/dist/interface/assets/Recordings-Cz4uWsI9.js +0 -1
  340. package/dist/interface/assets/SettingsAccount-CALY2rH0.js +0 -1
  341. package/dist/interface/assets/SettingsAccount-_zSgGuBE.js +0 -1
  342. package/dist/interface/assets/SettingsAppearance-z9tBty3q.js +0 -1
  343. package/dist/interface/assets/SettingsBackup-JI_xqcVS.js +0 -1
  344. package/dist/interface/assets/SettingsMqtt-B_tzet_5.js +0 -1
  345. package/dist/interface/assets/SettingsNotifications-FWWveQMH.js +0 -2
  346. package/dist/interface/assets/SettingsRecordings-D-S7rofE.js +0 -1
  347. package/dist/interface/assets/SettingsRemote-CVuDUBMM.js +0 -1
  348. package/dist/interface/assets/SettingsRemote-T38YVHal.css +0 -1
  349. package/dist/interface/assets/SettingsSystem-J7ZT7oRr.js +0 -2
  350. package/dist/interface/assets/SettingsUsers-DvuiYjNg.js +0 -1
  351. package/dist/interface/assets/Terminal-CNzw8wk3.js +0 -4
  352. package/dist/interface/assets/VersionsHandler-CsXazSWK.js +0 -7
  353. package/dist/interface/assets/Workers-BXH8IccG.js +0 -2
  354. package/dist/interface/assets/api-C31uUd3g.css +0 -2
  355. package/dist/interface/assets/api-DR6W2XWy.js +0 -2
  356. package/dist/interface/assets/auth-BJf6VFls.js +0 -1
  357. package/dist/interface/assets/automations-Dt5J3kkY.js +0 -1
  358. package/dist/interface/assets/cloudHandoff-Yc4FJv_l.js +0 -1
  359. package/dist/interface/assets/instances-MscZjRfc.js +0 -1
  360. package/dist/interface/assets/main-4pJkMgxg.js +0 -3
  361. package/dist/interface/assets/nodeDefinitions-5BjF3SJ8.js +0 -1
  362. package/dist/interface/assets/plugins-VeCjoaEi.js +0 -1
  363. package/dist/interface/assets/round-restart-alt-CcJGggln.js +0 -1
  364. package/dist/interface/assets/router-BFG1ClJo.js +0 -2
  365. package/dist/interface/assets/shares-D5xo0sht.js +0 -1
  366. package/dist/interface/assets/transit-connection-variant-CXkATe8I.js +0 -1
  367. package/dist/interface/assets/types-Dyn_Sb2s.js +0 -1
  368. package/dist/interface/assets/useBackupRestore-B-yCV4DL.js +0 -1
  369. package/dist/interface/assets/useCameraOptions-B2lIc9JO.js +0 -1
  370. package/dist/interface/assets/useCuiDialog-DLoFzodG.js +0 -2
  371. package/dist/interface/assets/useLogsSocket-4F2-d9fa.css +0 -1
  372. package/dist/interface/assets/useLogsSocket-B1sCzRXK.js +0 -5
  373. package/dist/interface/assets/vendor-cameraui-DDdtrYBn.js +0 -1978
  374. package/dist/interface/assets/vendor-core-CZuWsjWr.js +0 -1
  375. package/dist/interface/assets/view-grid-DRwNJzxD.js +0 -1
  376. package/dist/server/src/camera/decoder/audio-source.js.map +0 -1
  377. package/dist/server/src/camera/decoder/frame-source.js.map +0 -1
  378. package/dist/server/src/camera/decoder/ptz-autotracker.js +0 -342
  379. package/dist/server/src/camera/decoder/ptz-autotracker.js.map +0 -1
  380. package/dist/server/src/camera/decoder/snapshot-source.js.map +0 -1
  381. /package/dist/server/src/camera/decoder/{audio-source.d.ts → sources/audio-source.d.ts} +0 -0
@@ -0,0 +1,445 @@
1
+ import { PromiseTimeout } from '@camera.ui/common/utils';
2
+ import { isNoRespondersError } from '@camera.ui/rpc';
3
+ import { SensorType } from '@camera.ui/sdk';
4
+ import { NamespaceManager } from '../../rpc/namespaces.js';
5
+ import { EVENT_THUMB_MAX_WIDTH } from './event-thumbnailer.js';
6
+ import { hasSecondaryModelSpec, isVideoInputSpec } from './plugin-registry.js';
7
+ import { DETECT_TIMEOUT_MS } from './types.js';
8
+ const DETECTION_THUMB_MAX_WIDTH = 640;
9
+ const DETECTION_THUMB_MIN_CROP = 160;
10
+ const DETECTION_THUMB_HQ_MAX_WIDTH = 640;
11
+ const DETECTION_THUMB_HQ_MIN_CROP = 640;
12
+ const DETECTION_THUMB_HQ_QUALITY = 80;
13
+ const ATTRIBUTE_THUMB_MAX_WIDTH = 640;
14
+ const ATTRIBUTE_THUMB_MIN_CROP = 128;
15
+ const SECONDARY_CONSUMERS = [
16
+ { type: SensorType.Face, key: 'face' },
17
+ { type: SensorType.LicensePlate, key: 'lpd' },
18
+ { type: SensorType.Clip, key: 'clip' },
19
+ ];
20
+ export class SecondaryStage {
21
+ plugins;
22
+ pipeline;
23
+ frameScaler;
24
+ proxy;
25
+ logger;
26
+ isCancelled;
27
+ nvrProxy;
28
+ nvrProxyPromise;
29
+ constructor(plugins, pipeline, frameScaler, proxy, logger, isCancelled) {
30
+ this.plugins = plugins;
31
+ this.pipeline = pipeline;
32
+ this.frameScaler = frameScaler;
33
+ this.proxy = proxy;
34
+ this.logger = logger;
35
+ this.isCancelled = isCancelled;
36
+ }
37
+ async detect(rawFrame, objectDetections, results) {
38
+ const regionMap = await this.prepareSecondaryRegions(rawFrame, objectDetections);
39
+ await this.runAllSecondaries(regionMap, results);
40
+ }
41
+ // no loop frame available: secondaries see the whole frame instead of
42
+ // per-detection crops, returns the scene JPEG for the event thumbnail
43
+ async detectFullFrame(rawFrame, results) {
44
+ const regionMap = await this.prepareFullFrameRegions(rawFrame);
45
+ if (regionMap.size > 0) {
46
+ await this.runAllSecondaries(regionMap, results);
47
+ }
48
+ try {
49
+ return await this.frameScaler.frameToJPEG(rawFrame, EVENT_THUMB_MAX_WIDTH);
50
+ }
51
+ catch (error) {
52
+ this.logger.debug('Full-frame scene thumbnail failed:', error);
53
+ return null;
54
+ }
55
+ }
56
+ async generateThumbnails(sourceFrame, scaler, usingHq, objectDetections, results) {
57
+ const thumbnails = [];
58
+ const attributePadding = usingHq ? 0.4 : 0.75;
59
+ const detectionMaxWidth = usingHq ? DETECTION_THUMB_HQ_MAX_WIDTH : DETECTION_THUMB_MAX_WIDTH;
60
+ const detectionMinCrop = usingHq ? DETECTION_THUMB_HQ_MIN_CROP : DETECTION_THUMB_MIN_CROP;
61
+ const detectionQuality = usingHq ? DETECTION_THUMB_HQ_QUALITY : undefined;
62
+ const objectCrops = await scaler.cropToJPEG(sourceFrame, objectDetections, {
63
+ maxWidth: detectionMaxWidth,
64
+ padding: 0.3,
65
+ minCrop: detectionMinCrop,
66
+ quality: detectionQuality,
67
+ });
68
+ for (const crop of objectCrops) {
69
+ const detection = objectDetections[crop.index];
70
+ if (detection) {
71
+ thumbnails.push({
72
+ label: detection.label,
73
+ score: detection.confidence,
74
+ jpeg: crop.jpeg,
75
+ area: detection.box.width * detection.box.height,
76
+ onEdge: this.isOnEdge(detection.box),
77
+ trackId: 'trackId' in detection ? detection.trackId : undefined,
78
+ speed: 'trackSpeed' in detection ? detection.trackSpeed : undefined,
79
+ });
80
+ }
81
+ }
82
+ if (results.face?.detections) {
83
+ const faceCrops = await scaler.cropToJPEG(sourceFrame, results.face.detections, {
84
+ maxWidth: ATTRIBUTE_THUMB_MAX_WIDTH,
85
+ padding: attributePadding,
86
+ minCrop: ATTRIBUTE_THUMB_MIN_CROP,
87
+ });
88
+ for (const crop of faceCrops) {
89
+ const detection = results.face.detections[crop.index];
90
+ if (detection) {
91
+ // enrichSegment persists unknown faces to the face store from this
92
+ detection.thumbnail ??= crop.jpeg;
93
+ thumbnails.push({
94
+ label: `face:${detection.identity ?? 'unknown'}`,
95
+ score: detection.confidence,
96
+ jpeg: crop.jpeg,
97
+ area: detection.box.width * detection.box.height,
98
+ onEdge: this.isOnEdge(detection.box),
99
+ });
100
+ }
101
+ }
102
+ }
103
+ if (results.licensePlate?.detections) {
104
+ const plateCrops = await scaler.cropToJPEG(sourceFrame, results.licensePlate.detections, {
105
+ maxWidth: ATTRIBUTE_THUMB_MAX_WIDTH,
106
+ padding: attributePadding,
107
+ minCrop: ATTRIBUTE_THUMB_MIN_CROP,
108
+ });
109
+ for (const crop of plateCrops) {
110
+ const detection = results.licensePlate.detections[crop.index];
111
+ if (detection) {
112
+ thumbnails.push({
113
+ label: `plate:${detection.plateText ?? 'unknown'}`,
114
+ score: detection.confidence,
115
+ jpeg: crop.jpeg,
116
+ area: detection.box.width * detection.box.height,
117
+ onEdge: this.isOnEdge(detection.box),
118
+ });
119
+ }
120
+ }
121
+ }
122
+ if (results.classifiers) {
123
+ for (const classifierResult of Object.values(results.classifiers)) {
124
+ const clsCrops = await scaler.cropToJPEG(sourceFrame, classifierResult.detections, {
125
+ maxWidth: detectionMaxWidth,
126
+ padding: 0.3,
127
+ minCrop: detectionMinCrop,
128
+ quality: detectionQuality,
129
+ });
130
+ for (const crop of clsCrops) {
131
+ const detection = classifierResult.detections[crop.index];
132
+ if (detection) {
133
+ thumbnails.push({
134
+ label: `class:${detection.label}`,
135
+ score: detection.confidence,
136
+ jpeg: crop.jpeg,
137
+ area: detection.box.width * detection.box.height,
138
+ onEdge: this.isOnEdge(detection.box),
139
+ });
140
+ }
141
+ }
142
+ }
143
+ }
144
+ return thumbnails;
145
+ }
146
+ async runAllSecondaries(regionMap, results) {
147
+ await Promise.allSettled([
148
+ this.runSecondaryDetection(SensorType.Face, results, () => this.runFaceDetection(regionMap.get('face') ?? [])),
149
+ this.runSecondaryDetection(SensorType.LicensePlate, results, () => this.runLicensePlateDetection(regionMap.get('lpd') ?? [])),
150
+ this.runSecondaryDetection(SensorType.Classifier, results, () => this.runClassifierDetections(regionMap)),
151
+ this.runSecondaryDetection(SensorType.Clip, results, () => this.runClipDetection(regionMap.get('clip') ?? [])),
152
+ ]);
153
+ if (results.face?.detections.length) {
154
+ const facePlugin = this.plugins.get(SensorType.Face);
155
+ results.faceEmbeddingModel = facePlugin?.modelSpec?.embeddingModel;
156
+ }
157
+ }
158
+ collectConsumers(requireFrames) {
159
+ const consumers = [];
160
+ for (const { type, key } of SECONDARY_CONSUMERS) {
161
+ const plugin = this.plugins.get(type);
162
+ if (!plugin || (requireFrames && !plugin.requiresFrames))
163
+ continue;
164
+ if (hasSecondaryModelSpec(plugin.modelSpec) && isVideoInputSpec(plugin.modelSpec.input)) {
165
+ consumers.push({ key, triggerLabels: plugin.modelSpec.triggerLabels, input: plugin.modelSpec.input });
166
+ }
167
+ }
168
+ for (const plugin of this.plugins.getAll(SensorType.Classifier)) {
169
+ if (requireFrames && !plugin.requiresFrames)
170
+ continue;
171
+ if (hasSecondaryModelSpec(plugin.modelSpec) && isVideoInputSpec(plugin.modelSpec.input)) {
172
+ consumers.push({ key: `classifier:${plugin.pluginId}`, triggerLabels: plugin.modelSpec.triggerLabels, input: plugin.modelSpec.input });
173
+ }
174
+ }
175
+ return consumers;
176
+ }
177
+ async prepareSecondaryRegions(rawFrame, objectDetections) {
178
+ const result = new Map();
179
+ const consumers = this.collectConsumers(false);
180
+ if (consumers.length === 0)
181
+ return result;
182
+ for (const detection of objectDetections) {
183
+ const detLabel = detection.label.toLowerCase();
184
+ const targets = [];
185
+ for (const consumer of consumers) {
186
+ if (consumer.triggerLabels.length === 0 || consumer.triggerLabels.some((l) => l.toLowerCase() === detLabel)) {
187
+ targets.push({ key: consumer.key, width: consumer.input.width, height: consumer.input.height, format: consumer.input.format });
188
+ }
189
+ }
190
+ if (targets.length === 0)
191
+ continue;
192
+ // consumers with identical dimensions share one scaled region
193
+ const uniqueTargets = [];
194
+ const dupeMap = new Map(); // sizeKey → [consumerKey, ...]
195
+ for (const t of targets) {
196
+ const sizeKey = `${t.width}x${t.height}_${t.format}`;
197
+ const existing = dupeMap.get(sizeKey);
198
+ if (existing) {
199
+ existing.push(t.key);
200
+ }
201
+ else {
202
+ dupeMap.set(sizeKey, [t.key]);
203
+ uniqueTargets.push(t);
204
+ }
205
+ }
206
+ const regions = await this.frameScaler.cropAndScaleMulti(rawFrame, detection, uniqueTargets);
207
+ for (const [_sizeKey, consumerKeys] of dupeMap) {
208
+ const primaryKey = consumerKeys[0];
209
+ const region = regions.get(primaryKey);
210
+ if (!region)
211
+ continue;
212
+ for (const key of consumerKeys) {
213
+ const list = result.get(key);
214
+ if (list) {
215
+ list.push(region);
216
+ }
217
+ else {
218
+ result.set(key, [region]);
219
+ }
220
+ }
221
+ }
222
+ }
223
+ return result;
224
+ }
225
+ async prepareFullFrameRegions(rawFrame) {
226
+ const result = new Map();
227
+ const consumers = this.collectConsumers(true);
228
+ if (consumers.length === 0)
229
+ return result;
230
+ const frameWidth = rawFrame.width;
231
+ const frameHeight = rawFrame.height;
232
+ const fullFrameDetection = {
233
+ label: 'person',
234
+ confidence: 1.0,
235
+ box: { x: 0, y: 0, width: 1, height: 1 },
236
+ };
237
+ for (const consumer of consumers) {
238
+ const scaled = await this.frameScaler.scaleToSpec(rawFrame, consumer.input);
239
+ if (!scaled)
240
+ continue;
241
+ const region = {
242
+ frame: this.frameScaler.toVideoFrameData(scaled, `fullframe:${consumer.key}`),
243
+ detection: fullFrameDetection,
244
+ offset: { x: 0, y: 0 },
245
+ cropSize: { width: frameWidth, height: frameHeight },
246
+ originalSize: { width: frameWidth, height: frameHeight },
247
+ };
248
+ result.set(consumer.key, [region]);
249
+ }
250
+ return result;
251
+ }
252
+ async runSecondaryDetection(type, results, fn) {
253
+ let detections;
254
+ try {
255
+ detections = await fn();
256
+ }
257
+ catch (error) {
258
+ if (this.isCancelled() || isNoRespondersError(error))
259
+ return;
260
+ const logType = type === SensorType.Face ? 'Face' : type === SensorType.LicensePlate ? 'License plate' : type === SensorType.Clip ? 'CLIP' : 'Classifier';
261
+ this.logger.error(`${logType} detection error:`, error);
262
+ }
263
+ if (!detections)
264
+ return;
265
+ if (type === SensorType.Face) {
266
+ results.face = detections;
267
+ await this.resolveFaceIdentities(results.face.detections);
268
+ }
269
+ else if (type === SensorType.LicensePlate) {
270
+ results.licensePlate = detections;
271
+ }
272
+ else if (type === SensorType.Clip) {
273
+ results.clip = detections;
274
+ const clipPlugin = this.plugins.get(SensorType.Clip);
275
+ results.clipEmbeddingModel = clipPlugin?.modelSpec?.embeddingModel;
276
+ }
277
+ else if (type === SensorType.Classifier) {
278
+ results.classifiers ??= {};
279
+ for (const { pluginId, result } of detections) {
280
+ results.classifiers[pluginId] = result;
281
+ }
282
+ if (Object.keys(results.classifiers).length === 0)
283
+ delete results.classifiers;
284
+ }
285
+ }
286
+ async runFaceDetection(croppedRegions) {
287
+ const facePlugin = this.plugins.get(SensorType.Face);
288
+ if (!facePlugin || croppedRegions.length === 0)
289
+ return undefined;
290
+ const batchResults = await PromiseTimeout(facePlugin.proxy.detectFaces(this.prepareSecondaryFrames(croppedRegions)), DETECT_TIMEOUT_MS, undefined, `Face detection timed out after ${DETECT_TIMEOUT_MS}ms`);
291
+ const allFaces = [];
292
+ for (let i = 0; i < batchResults.length; i++) {
293
+ const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
294
+ for (const face of batchResults[i].detections) {
295
+ const transformed = this.transformBoxToOriginal(face.box, croppedRegions[i]);
296
+ allFaces.push({ ...face, box: transformed, parentTrackId });
297
+ }
298
+ }
299
+ if (allFaces.length === 0)
300
+ return { detected: false, detections: [] };
301
+ // NMS only, the crops come from already zone-filtered object detections
302
+ const deduped = this.pipeline.runNms(allFaces);
303
+ return { detected: deduped.length > 0, detections: deduped };
304
+ }
305
+ async runLicensePlateDetection(croppedRegions) {
306
+ const lpdPlugin = this.plugins.get(SensorType.LicensePlate);
307
+ if (!lpdPlugin || croppedRegions.length === 0)
308
+ return undefined;
309
+ const batchResults = await PromiseTimeout(lpdPlugin.proxy.detectLicensePlates(this.prepareSecondaryFrames(croppedRegions)), DETECT_TIMEOUT_MS, undefined, `License plate detection timed out after ${DETECT_TIMEOUT_MS}ms`);
310
+ const allPlates = [];
311
+ for (let i = 0; i < batchResults.length; i++) {
312
+ const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
313
+ for (const plate of batchResults[i].detections) {
314
+ allPlates.push({ ...plate, box: this.transformBoxToOriginal(plate.box, croppedRegions[i]), parentTrackId });
315
+ }
316
+ }
317
+ if (allPlates.length === 0)
318
+ return { detected: false, detections: [] };
319
+ // NMS only, the crops come from already zone-filtered object detections
320
+ const deduped = this.pipeline.runNms(allPlates);
321
+ return { detected: deduped.length > 0, detections: deduped };
322
+ }
323
+ async runClassifierDetections(regionMap) {
324
+ const classifierPlugins = this.plugins.getAll(SensorType.Classifier);
325
+ if (classifierPlugins.length === 0)
326
+ return [];
327
+ const promises = [];
328
+ for (const classifierPlugin of classifierPlugins) {
329
+ const croppedRegions = regionMap.get(`classifier:${classifierPlugin.pluginId}`);
330
+ if (!croppedRegions || croppedRegions.length === 0)
331
+ continue;
332
+ const runClassifier = async () => {
333
+ const batchResults = await PromiseTimeout(classifierPlugin.proxy.detectClassifications(this.prepareSecondaryFrames(croppedRegions)), DETECT_TIMEOUT_MS, undefined, `Classifier detection timed out after ${DETECT_TIMEOUT_MS}ms`);
334
+ const allDetections = [];
335
+ for (let i = 0; i < batchResults.length; i++) {
336
+ const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
337
+ for (const detection of batchResults[i].detections) {
338
+ allDetections.push({ ...detection, box: this.transformBoxToOriginal(detection.box, croppedRegions[i]), parentTrackId });
339
+ }
340
+ }
341
+ if (allDetections.length === 0)
342
+ return undefined;
343
+ const deduped = this.pipeline.runNms(allDetections);
344
+ if (deduped.length === 0)
345
+ return undefined;
346
+ return { pluginId: classifierPlugin.pluginId, result: { detected: true, detections: deduped } };
347
+ };
348
+ promises.push(runClassifier());
349
+ }
350
+ const settled = await Promise.all(promises);
351
+ return settled.filter((r) => r !== undefined);
352
+ }
353
+ async runClipDetection(croppedRegions) {
354
+ const clipPlugin = this.plugins.get(SensorType.Clip);
355
+ if (!clipPlugin || croppedRegions.length === 0)
356
+ return undefined;
357
+ const batchResults = await PromiseTimeout(clipPlugin.proxy.detectEmbeddings(this.prepareSecondaryFrames(croppedRegions)), DETECT_TIMEOUT_MS, undefined, `CLIP detection timed out after ${DETECT_TIMEOUT_MS}ms`);
358
+ const allEmbeddings = [];
359
+ for (let i = 0; i < batchResults.length; i++) {
360
+ if (batchResults[i].embeddings && batchResults[i].embeddings.length > 0) {
361
+ const parentTrackId = 'trackId' in croppedRegions[i].detection ? croppedRegions[i].detection.trackId : undefined;
362
+ for (const emb of batchResults[i].embeddings) {
363
+ const transformed = this.transformBoxToOriginal(emb.box, croppedRegions[i]);
364
+ allEmbeddings.push({ ...emb, box: transformed, parentTrackId });
365
+ }
366
+ }
367
+ }
368
+ if (allEmbeddings.length === 0)
369
+ return undefined;
370
+ const embeddingModel = clipPlugin.modelSpec?.embeddingModel ?? '';
371
+ return { embeddings: allEmbeddings, embeddingModel };
372
+ }
373
+ prepareSecondaryFrames(croppedRegions) {
374
+ return croppedRegions.map((r, i) => ({ ...r.frame, id: String(i), label: r.detection.label }));
375
+ }
376
+ async resolveFaceIdentities(faces) {
377
+ const withEmbeddings = faces.filter((f) => f.embedding?.length);
378
+ if (!withEmbeddings.length)
379
+ return;
380
+ const facePlugin = this.plugins.get(SensorType.Face);
381
+ const embeddingModel = facePlugin?.modelSpec?.embeddingModel;
382
+ if (!embeddingModel)
383
+ return;
384
+ const nvr = await this.getNvrProxy();
385
+ if (!nvr)
386
+ return;
387
+ try {
388
+ const embeddings = withEmbeddings.map((f) => f.embedding);
389
+ const matches = await nvr.matchFaces(embeddings, embeddingModel);
390
+ for (let i = 0; i < withEmbeddings.length; i++) {
391
+ if (matches[i]) {
392
+ withEmbeddings[i].identity = matches[i].identity;
393
+ }
394
+ }
395
+ }
396
+ catch (error) {
397
+ if (this.isCancelled() || isNoRespondersError(error))
398
+ return;
399
+ this.logger.error('Could not resolve face identities:', error);
400
+ }
401
+ }
402
+ transformBoxToOriginal(box, region) {
403
+ // boxes are normalized to the scaled crop, map back through the original
404
+ // crop dimensions before scaling
405
+ const pixelX = box.x * region.cropSize.width + region.offset.x;
406
+ const pixelY = box.y * region.cropSize.height + region.offset.y;
407
+ const pixelW = box.width * region.cropSize.width;
408
+ const pixelH = box.height * region.cropSize.height;
409
+ return {
410
+ x: pixelX / region.originalSize.width,
411
+ y: pixelY / region.originalSize.height,
412
+ width: pixelW / region.originalSize.width,
413
+ height: pixelH / region.originalSize.height,
414
+ };
415
+ }
416
+ isOnEdge(box) {
417
+ return box.x < 0.02 || box.y < 0.02 || box.x + box.width > 0.98 || box.y + box.height > 0.98;
418
+ }
419
+ getNvrProxy() {
420
+ if (this.nvrProxy)
421
+ return Promise.resolve(this.nvrProxy);
422
+ this.nvrProxyPromise ??= this.resolveNvrProxy().finally(() => {
423
+ this.nvrProxyPromise = undefined;
424
+ });
425
+ return this.nvrProxyPromise;
426
+ }
427
+ async resolveNvrProxy() {
428
+ try {
429
+ const coreManagerProxy = this.proxy.createProxy(NamespaceManager.coreManagerNamespaces().coreManagerRpc);
430
+ const plugin = await coreManagerProxy.getPlugin('@camera.ui/camera-ui-nvr');
431
+ if (!plugin) {
432
+ return undefined;
433
+ }
434
+ const ns = NamespaceManager.pluginNamespaces(plugin.id);
435
+ const connection = this.proxy.createProxy(ns.pluginChildRpc, { isolatedConnection: true });
436
+ this.nvrProxy = connection.proxy;
437
+ return this.nvrProxy;
438
+ }
439
+ catch (error) {
440
+ this.logger.error('NVR proxy resolution failed:', error);
441
+ return undefined;
442
+ }
443
+ }
444
+ }
445
+ //# sourceMappingURL=secondary-stage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"secondary-stage.js","sourceRoot":"","sources":["../../../../../src/camera/decoder/secondary-stage.ts"],"names":[],"mappings":"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"}
@@ -8,7 +8,7 @@ export class AudioSource {
8
8
  filter;
9
9
  _isStreaming = false;
10
10
  shouldRun = false;
11
- // Mailbox state — single-slot frame buffer with monotonic id
11
+ // single-slot mailbox with monotonic id
12
12
  latest;
13
13
  nextId = 0;
14
14
  waiter;
@@ -48,7 +48,7 @@ export class AudioSource {
48
48
  this.decoder = await Decoder.create(audioStream, {
49
49
  exitOnError: false,
50
50
  });
51
- // Resample to plugin spec (pattern from rtp-session.ts:236-241)
51
+ // resample to plugin spec
52
52
  const sampleFmt = this.config.format === 'pcm16' ? AV_SAMPLE_FMT_S16 : AV_SAMPLE_FMT_FLT;
53
53
  const layout = this.config.channels === 1 ? 'mono' : 'stereo';
54
54
  const chain = FilterPreset.chain().aformat(sampleFmt, this.config.sampleRate, layout);
@@ -0,0 +1 @@
1
+ {"version":3,"file":"audio-source.js","sourceRoot":"","sources":["../../../../../../src/camera/decoder/sources/audio-source.ts"],"names":[],"mappings":"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"}
@@ -6,6 +6,7 @@ export interface FrameSourceConfig {
6
6
  snapshotUrl: string;
7
7
  fps: number;
8
8
  snapshotTimeoutMs?: number;
9
+ snapshotProvider?: () => Promise<Buffer | null>;
9
10
  }
10
11
  export interface FrameSnap {
11
12
  frame: Frame;
@@ -19,6 +20,8 @@ export declare class FrameHandle implements AsyncDisposable {
19
20
  private constructor();
20
21
  static fromClonedFrame(frame: Frame): FrameHandle;
21
22
  static fromUrl(url: string, timeoutMs: number): Promise<FrameHandle>;
23
+ static fromBuffer(data: Buffer): Promise<FrameHandle>;
24
+ private static decodeFirstFrame;
22
25
  [Symbol.asyncDispose](): Promise<void>;
23
26
  }
24
27
  export declare class FrameSource {
@@ -51,6 +54,7 @@ export declare class FrameSource {
51
54
  nextFrame(lastId: number): Promise<FrameSnap | undefined>;
52
55
  peekLatestFrame(): FrameHandle | null;
53
56
  fetchSnapshotFrame(): Promise<FrameHandle | null>;
57
+ private fetchSnapshotHandle;
54
58
  private wakeWaiter;
55
59
  private runProducer;
56
60
  }
@@ -14,7 +14,7 @@ export class FrameHandle {
14
14
  return new FrameHandle(frame);
15
15
  }
16
16
  static async fromUrl(url, timeoutMs) {
17
- // libavformat expects `timeout` in microseconds for both HTTP and RTSP demuxers.
17
+ // libavformat expects timeout in microseconds
18
18
  const timeoutUs = Math.max(1, Math.floor(timeoutMs * 1000));
19
19
  const isRTSP = url.startsWith('rtsp://') || url.startsWith('rtsps://');
20
20
  const demuxer = await Demuxer.open(url, {
@@ -24,6 +24,13 @@ export class FrameHandle {
24
24
  user_agent: 'camera.ui FrameWorker',
25
25
  },
26
26
  });
27
+ return FrameHandle.decodeFirstFrame(demuxer);
28
+ }
29
+ static async fromBuffer(data) {
30
+ const demuxer = await Demuxer.open(data);
31
+ return FrameHandle.decodeFirstFrame(demuxer);
32
+ }
33
+ static async decodeFirstFrame(demuxer) {
27
34
  let decoder;
28
35
  let firstFrame;
29
36
  try {
@@ -32,8 +39,7 @@ export class FrameHandle {
32
39
  throw new Error('No video stream in snapshot source');
33
40
  }
34
41
  decoder = await Decoder.create(videoStream, { exitOnError: false });
35
- // The frames() generator yields nulls for packets that produce no frame;
36
- // keep iterating until a frame appears or the stream ends.
42
+ // frames() yields null for packets that produce no frame, keep iterating
37
43
  const packets = demuxer.packets(videoStream.index);
38
44
  const frames = decoder.frames(packets);
39
45
  for await (const frame of frames) {
@@ -110,7 +116,7 @@ export class FrameSource {
110
116
  _isStreaming = false;
111
117
  _resolvedFps;
112
118
  shouldRun = false;
113
- // Mailbox state — single-slot frame buffer with monotonic id
119
+ // single-slot mailbox with monotonic id
114
120
  latest;
115
121
  nextId = 0;
116
122
  waiter;
@@ -172,9 +178,7 @@ export class FrameSource {
172
178
  hardware: this._hardwareContext,
173
179
  exitOnError: false,
174
180
  });
175
- // Resolve FPS: user-configured value, or native stream rate as fallback.
176
- // Stored as _resolvedFps so consumers (DetectionCoordinator, etc.) can
177
- // read the actual effective rate via the `fps` getter.
181
+ // user-configured fps, native stream rate as fallback
178
182
  let nativeFps = videoStream.avgFrameRate.num / videoStream.avgFrameRate.den;
179
183
  if (!isFinite(nativeFps) || nativeFps <= 0 || isNaN(nativeFps)) {
180
184
  nativeFps = 20;
@@ -199,8 +203,8 @@ export class FrameSource {
199
203
  return;
200
204
  this._isStreaming = false;
201
205
  this._resolvedFps = undefined;
202
- // Mark ended and wake any waiting consumer BEFORE awaiting the producer
203
- // so the consumer can break out of its loop and stop holding it up.
206
+ // wake waiting consumers BEFORE awaiting the producer, otherwise they
207
+ // hold it up
204
208
  this.ended = true;
205
209
  this.wakeWaiter();
206
210
  this.input?.interrupt();
@@ -263,12 +267,12 @@ export class FrameSource {
263
267
  async fetchSnapshotFrame() {
264
268
  if (!this.inflightFetch) {
265
269
  const timeoutMs = this.config.snapshotTimeoutMs ?? FrameSource.FETCH_DEFAULT_TIMEOUT_MS;
266
- const thisFetch = FrameHandle.fromUrl(this.config.snapshotUrl, timeoutMs).catch((e) => {
270
+ const thisFetch = this.fetchSnapshotHandle(timeoutMs).catch((e) => {
267
271
  this.logger.debug('fetchSnapshotFrame failed:', e);
268
272
  return null;
269
273
  });
270
274
  this.inflightFetch = thisFetch;
271
- // Per-fetch dispose timer via closure so overlapping fetches don't share state.
275
+ // per-fetch dispose timer, overlapping fetches must not share state
272
276
  thisFetch.finally(() => {
273
277
  setTimeout(async () => {
274
278
  if (this.inflightFetch === thisFetch) {
@@ -291,6 +295,20 @@ export class FrameSource {
291
295
  const cloned = rootHandle.frame.clone();
292
296
  return cloned ? FrameHandle.fromClonedFrame(cloned) : null;
293
297
  }
298
+ async fetchSnapshotHandle(timeoutMs) {
299
+ if (this.config.snapshotProvider) {
300
+ try {
301
+ const jpeg = await this.config.snapshotProvider();
302
+ if (jpeg && jpeg.length > 0) {
303
+ return await FrameHandle.fromBuffer(jpeg);
304
+ }
305
+ }
306
+ catch {
307
+ // fall back to snapshotUrl
308
+ }
309
+ }
310
+ return FrameHandle.fromUrl(this.config.snapshotUrl, timeoutMs);
311
+ }
294
312
  wakeWaiter() {
295
313
  if (!this.waiter)
296
314
  return;
@@ -335,7 +353,7 @@ export class FrameSource {
335
353
  this.logger.trace('First frame received');
336
354
  firstFrame = false;
337
355
  }
338
- // Overwrite mailbox slot — dispose any un-picked-up frame so we don't leak.
356
+ // dispose any un-picked-up frame before overwriting the slot
339
357
  if (this.latest) {
340
358
  try {
341
359
  this.latest.frame[Symbol.dispose]?.();