@camera.ui/server 0.0.49 → 0.0.50-internal.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (605) hide show
  1. package/dist/interface/assets/@xterm.DYP7pi_n.0.0.50-internal.1.css +32 -0
  2. package/dist/interface/assets/Adminpanel.BKek2EMH.0.0.50-internal.1.css +1 -0
  3. package/dist/interface/assets/Cameras.BDWZJqPN.0.0.50-internal.1.css +1 -0
  4. package/dist/interface/assets/Camview.BFUFMoNX.0.0.50-internal.1.css +1 -0
  5. package/dist/interface/assets/CuiConsole.DCYyxdVg.0.0.50-internal.1.css +1 -0
  6. package/dist/interface/assets/CuiPluginCard.yF8V0SZY.0.0.50-internal.1.css +1 -0
  7. package/dist/interface/assets/CuiTimeline.BkIwlYtw.0.0.50-internal.1.css +1 -0
  8. package/dist/interface/assets/Plugin.DJElsAn5.0.0.50-internal.1.css +1 -0
  9. package/dist/interface/assets/Plugins.0h77qnmN.0.0.50-internal.1.css +1 -0
  10. package/dist/interface/assets/Settings.CkgfRkQr.0.0.50-internal.1.css +1 -0
  11. package/dist/interface/assets/SettingsAccount.DeFul3eQ.0.0.50-internal.1.css +1 -0
  12. package/dist/interface/assets/main.Cip9LkS3.0.0.50-internal.1.css +1 -0
  13. package/dist/interface/assets/worker-base.jEXLGV2h.0.0.50-internal.1.js +1332 -0
  14. package/dist/interface/assets/worker-json.DgwNIOck.0.0.50-internal.1.js +1626 -0
  15. package/dist/interface/assets/worker-yaml.B3uUYINB.0.0.50-internal.1.js +5819 -0
  16. package/dist/interface/fonts/InterVariable.woff2 +0 -0
  17. package/dist/interface/index.html +48 -38
  18. package/dist/interface/js/@intlify.BkGPX90O.0.0.50-internal.1.js +15 -0
  19. package/dist/interface/js/@kurkle.D8fDXNIl.0.0.50-internal.1.js +6 -0
  20. package/dist/interface/js/@primeuix.BFAY2Bk9.0.0.50-internal.1.js +5722 -0
  21. package/dist/interface/js/@primevue.CiB2EGly.0.0.50-internal.1.js +57 -0
  22. package/dist/interface/js/@tanstack.DxMw_rJn.0.0.50-internal.1.js +1 -0
  23. package/dist/interface/{@vee-validate.DHkwupr6.0.0.49.js → js/@vee-validate.RxZ3hn6V.0.0.50-internal.1.js} +2 -2
  24. package/dist/interface/js/@vue.B5vqhCp2.0.0.50-internal.1.js +17 -0
  25. package/dist/interface/js/@vueuse.C-k73ACm.0.0.50-internal.1.js +1 -0
  26. package/dist/interface/{@xterm.D6R4zI7m.0.0.49.js → js/@xterm.DIUBesyz.0.0.50-internal.1.js} +8 -8
  27. package/dist/interface/js/Adminpanel.DumNu6GD.0.0.50-internal.1.js +1 -0
  28. package/dist/interface/js/Camera.BuosoqFl.0.0.50-internal.1.js +1 -0
  29. package/dist/interface/js/Cameras.A7NJflGG.0.0.50-internal.1.js +482 -0
  30. package/dist/interface/js/Cammesh.Dv3C0UiR.0.0.50-internal.1.js +1 -0
  31. package/dist/interface/js/Camview.GgjJp7JR.0.0.50-internal.1.js +1 -0
  32. package/dist/interface/js/Config.BL3L-BFE.0.0.50-internal.1.js +2 -0
  33. package/dist/interface/js/Console.CxwRmUVF.0.0.50-internal.1.js +4 -0
  34. package/dist/interface/js/CuiConsole.D16kkT6R.0.0.50-internal.1.js +1 -0
  35. package/dist/interface/js/CuiPluginCard.Bkp__d8n.0.0.50-internal.1.js +4 -0
  36. package/dist/interface/js/CuiTimeline.C9HKvo0G.0.0.50-internal.1.js +1 -0
  37. package/dist/interface/js/FirstSteps.QuJjtAtF.0.0.50-internal.1.js +1 -0
  38. package/dist/interface/js/Plugin.BLUUbEej.0.0.50-internal.1.js +1 -0
  39. package/dist/interface/js/Plugins.DviCIk7w.0.0.50-internal.1.js +1 -0
  40. package/dist/interface/js/Recordings.Dsp07cHs.0.0.50-internal.1.js +1 -0
  41. package/dist/interface/js/Settings.Clx4y9gP.0.0.50-internal.1.js +1 -0
  42. package/dist/interface/js/SettingsAccount.cfY4-PYd.0.0.50-internal.1.js +1 -0
  43. package/dist/interface/js/SettingsAppearance.CBGZAazb.0.0.50-internal.1.js +1 -0
  44. package/dist/interface/js/SettingsAppearance.vue_vue_type_script_setup_true_lang.kxAPXcBy.0.0.50-internal.1.js +1 -0
  45. package/dist/interface/js/SettingsBackup.DOaJA4pp.0.0.50-internal.1.js +1 -0
  46. package/dist/interface/js/SettingsRecordings.BGcwL6tk.0.0.50-internal.1.js +1 -0
  47. package/dist/interface/js/SettingsRemote.BVU_w1Jm.0.0.50-internal.1.js +1 -0
  48. package/dist/interface/js/SettingsSystem.P0vy90vA.0.0.50-internal.1.js +1 -0
  49. package/dist/interface/js/SettingsUsers.DaP5m7eo.0.0.50-internal.1.js +1 -0
  50. package/dist/interface/js/VersionsHandler.vue_vue_type_script_setup_true_lang.MmrWYW3K.0.0.50-internal.1.js +4 -0
  51. package/dist/interface/js/ace-builds.C0aqA_3x.0.0.50-internal.1.js +1090 -0
  52. package/dist/interface/js/ace.config.C9wgzklI.0.0.50-internal.1.js +1 -0
  53. package/dist/interface/js/axios.DHr9lByg.0.0.50-internal.1.js +6 -0
  54. package/dist/interface/js/backup.BeH6lJ5t.0.0.50-internal.1.js +1 -0
  55. package/dist/interface/js/chart.js.BQHSWV_g.0.0.50-internal.1.js +13 -0
  56. package/dist/interface/js/close-circle.DDKMxauw.0.0.50-internal.1.js +1 -0
  57. package/dist/interface/js/dnd-core.dWz9rJqH.0.0.50-internal.1.js +1 -0
  58. package/dist/interface/{draggabilly.C0hZWkL0.0.0.49.js → js/draggabilly.D-iZIS1n.0.0.50-internal.1.js} +1 -1
  59. package/dist/interface/js/engine.io-client.BwxOddB_.0.0.50-internal.1.js +1 -0
  60. package/dist/interface/js/fast-deep-equal.Dz96RC_N.0.0.50-internal.1.js +1 -0
  61. package/dist/interface/js/highlight.js.CmcM8OM6.0.0.50-internal.1.js +3 -0
  62. package/dist/interface/js/linkify-it.BgLcBzlw.0.0.50-internal.1.js +1 -0
  63. package/dist/interface/js/main.6bOgRV7D.0.0.50-internal.1.js +31 -0
  64. package/dist/interface/{markdown-it.64FJJcTG.0.0.49.js → js/markdown-it.CTgfs-3p.0.0.50-internal.1.js} +1 -1
  65. package/dist/interface/{nprogress.DkWvUoHh.0.0.49.js → js/nprogress.CMhnq8jS.0.0.50-internal.1.js} +1 -1
  66. package/dist/interface/js/perfect-debounce.l0sNRNKZ.0.0.50-internal.1.js +1 -0
  67. package/dist/interface/js/pinia.CuC5ZfNs.0.0.50-internal.1.js +5 -0
  68. package/dist/interface/js/primelocale.Bga3dOQu.0.0.50-internal.1.js +1 -0
  69. package/dist/interface/js/primevue.DmwjJ4xV.0.0.50-internal.1.js +142 -0
  70. package/dist/interface/{qrcode.BixA_YE2.0.0.49.js → js/qrcode.DGZO3j1c.0.0.50-internal.1.js} +1 -1
  71. package/dist/interface/js/react-dnd-touch-backend.CEGHlD-T.0.0.50-internal.1.js +1 -0
  72. package/dist/interface/js/refresh-rounded.D0keXzBc.0.0.50-internal.1.js +1 -0
  73. package/dist/interface/js/rxjs.CiDbFOB0.0.0.50-internal.1.js +3 -0
  74. package/dist/interface/js/socket.io-client.BPcXPAHG.0.0.50-internal.1.js +1 -0
  75. package/dist/interface/js/socket.io-parser.DSGzrW_l.0.0.50-internal.1.js +1 -0
  76. package/dist/interface/js/system.BKlEObmx.0.0.50-internal.1.js +1 -0
  77. package/dist/interface/js/trash-fill.BDFILs86.0.0.50-internal.1.js +1 -0
  78. package/dist/interface/{unidragger.C8ueS-PW.0.0.49.js → js/unidragger.DcxsxHCS.0.0.50-internal.1.js} +1 -1
  79. package/dist/interface/js/uuid.C6aID195.0.0.50-internal.1.js +1 -0
  80. package/dist/interface/js/vee-validate.BGRg3oQ8.0.0.50-internal.1.js +5 -0
  81. package/dist/interface/js/vue-chartjs.B9yk2de7.0.0.50-internal.1.js +1 -0
  82. package/dist/interface/js/vue-i18n.DXDZITpf.0.0.50-internal.1.js +5 -0
  83. package/dist/interface/js/vue-inline-svg.BDYaTfbi.0.0.50-internal.1.js +1 -0
  84. package/dist/interface/js/vue-router.CFEDA008.0.0.50-internal.1.js +5 -0
  85. package/dist/interface/js/vue-zoomable.zqTafMgD.0.0.50-internal.1.js +1 -0
  86. package/dist/interface/js/vue.l0sNRNKZ.0.0.50-internal.1.js +1 -0
  87. package/dist/interface/js/vue3-dnd.BxM3dbYs.0.0.50-internal.1.js +1 -0
  88. package/dist/interface/js/zod.SKKegNRO.0.0.50-internal.1.js +1 -0
  89. package/dist/interface/js/zoom-out.B6SY9IIj.0.0.50-internal.1.js +1 -0
  90. package/dist/interface/manifest.webmanifest +1 -1
  91. package/dist/interface/pwa/favicon-32.ico +0 -0
  92. package/dist/interface/pwa/favicon-48.ico +0 -0
  93. package/dist/interface/sw.js +1 -1
  94. package/dist/server/package.json +57 -45
  95. package/dist/server/requirements.txt +12 -11
  96. package/dist/server/src/__init__.py +0 -0
  97. package/dist/server/src/_camera_ui_tools/__init__.py +0 -0
  98. package/dist/server/src/_camera_ui_tools/camera_ui_common/__init__.py +28 -0
  99. package/dist/server/src/_camera_ui_tools/camera_ui_common/camera_utils/utils.py +52 -0
  100. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/__init__.py +0 -0
  101. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/object_path.py +198 -0
  102. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/reactive.py +42 -0
  103. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/signal_handler.py +92 -0
  104. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/subscribed.py +21 -0
  105. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/task.py +39 -0
  106. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/thread.py +10 -0
  107. package/dist/server/src/_camera_ui_tools/camera_ui_common/common_utils/utils.py +91 -0
  108. package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/__init__.py +0 -0
  109. package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/ansicolor.py +62 -0
  110. package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/logger.py +178 -0
  111. package/dist/server/src/_camera_ui_tools/camera_ui_common/logger_service/test.py +116 -0
  112. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/__init__.py +350 -0
  113. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/__init__.py +0 -0
  114. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/base.py +237 -0
  115. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/client.py +256 -0
  116. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/connection.py +784 -0
  117. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/errors.py +745 -0
  118. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/messaging.py +57 -0
  119. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/rpc.py +227 -0
  120. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/base/rpc_generator.py +584 -0
  121. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/constants.py +96 -0
  122. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/typings.py +218 -0
  123. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/__init__.py +0 -0
  124. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/connection_state.py +86 -0
  125. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/logger.py +30 -0
  126. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/metrics.py +152 -0
  127. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/packer.py +20 -0
  128. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/routing.py +75 -0
  129. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/rpc.py +177 -0
  130. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/subscriptions.py +24 -0
  131. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/tasks.py +39 -0
  132. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/uid.py +37 -0
  133. package/dist/server/src/_camera_ui_tools/camera_ui_rpc_client/utils/validate.py +119 -0
  134. package/dist/server/src/_camera_ui_tools/camera_ui_types/__init__.py +1360 -0
  135. package/dist/server/src/_camera_ui_tools/camera_ui_types/hybrid_observer.py +338 -0
  136. package/dist/server/src/_camera_ui_tools/camera_ui_types/test.py +196 -0
  137. package/dist/server/src/api/controllers/auth.controller.d.ts +2 -2
  138. package/dist/server/src/api/controllers/auth.controller.js +49 -43
  139. package/dist/server/src/api/controllers/auth.controller.js.map +1 -1
  140. package/dist/server/src/api/controllers/backup.controller.js +1 -2
  141. package/dist/server/src/api/controllers/backup.controller.js.map +1 -1
  142. package/dist/server/src/api/controllers/cameras.controller.d.ts +13 -11
  143. package/dist/server/src/api/controllers/cameras.controller.js +314 -105
  144. package/dist/server/src/api/controllers/cameras.controller.js.map +1 -1
  145. package/dist/server/src/api/controllers/plugins.controller.d.ts +8 -8
  146. package/dist/server/src/api/controllers/plugins.controller.js +208 -244
  147. package/dist/server/src/api/controllers/plugins.controller.js.map +1 -1
  148. package/dist/server/src/api/controllers/system.controller.d.ts +1 -0
  149. package/dist/server/src/api/controllers/system.controller.js +22 -8
  150. package/dist/server/src/api/controllers/system.controller.js.map +1 -1
  151. package/dist/server/src/api/controllers/users.controller.d.ts +2 -2
  152. package/dist/server/src/api/controllers/users.controller.js +13 -25
  153. package/dist/server/src/api/controllers/users.controller.js.map +1 -1
  154. package/dist/server/src/api/database/checks.js +2 -2
  155. package/dist/server/src/api/database/checks.js.map +1 -1
  156. package/dist/server/src/api/database/index.d.ts +4 -7
  157. package/dist/server/src/api/database/index.js +59 -86
  158. package/dist/server/src/api/database/index.js.map +1 -1
  159. package/dist/server/src/api/database/migration.js +5 -141
  160. package/dist/server/src/api/database/migration.js.map +1 -1
  161. package/dist/server/src/api/database/selfcheck.js +5 -5
  162. package/dist/server/src/api/database/selfcheck.js.map +1 -1
  163. package/dist/server/src/api/database/types.d.ts +17 -25
  164. package/dist/server/src/api/go2rtc/api/discover.d.ts +30 -0
  165. package/dist/server/src/api/go2rtc/api/discover.js +162 -0
  166. package/dist/server/src/api/go2rtc/api/discover.js.map +1 -0
  167. package/dist/server/src/api/go2rtc/api/index.d.ts +1 -1
  168. package/dist/server/src/api/go2rtc/api/index.js +15 -4
  169. package/dist/server/src/api/go2rtc/api/index.js.map +1 -1
  170. package/dist/server/src/api/go2rtc/api/streams.d.ts +3 -1
  171. package/dist/server/src/api/go2rtc/api/streams.js +66 -9
  172. package/dist/server/src/api/go2rtc/api/streams.js.map +1 -1
  173. package/dist/server/src/api/go2rtc/index.d.ts +2 -0
  174. package/dist/server/src/api/go2rtc/index.js +3 -0
  175. package/dist/server/src/api/go2rtc/index.js.map +1 -1
  176. package/dist/server/src/api/go2rtc/queue.js +3 -3
  177. package/dist/server/src/api/go2rtc/queue.js.map +1 -1
  178. package/dist/server/src/api/go2rtc/types.d.ts +66 -11
  179. package/dist/server/src/api/index.d.ts +4 -0
  180. package/dist/server/src/api/index.js +45 -9
  181. package/dist/server/src/api/index.js.map +1 -1
  182. package/dist/server/src/api/middlewares/authPermission.middleware.d.ts +1 -0
  183. package/dist/server/src/api/middlewares/authPermission.middleware.js +11 -2
  184. package/dist/server/src/api/middlewares/authPermission.middleware.js.map +1 -1
  185. package/dist/server/src/api/middlewares/authValidation.middleware.js +20 -12
  186. package/dist/server/src/api/middlewares/authValidation.middleware.js.map +1 -1
  187. package/dist/server/src/api/middlewares/pagination.middleware.js +45 -53
  188. package/dist/server/src/api/middlewares/pagination.middleware.js.map +1 -1
  189. package/dist/server/src/api/plugins/proxy.plugin.d.ts +14 -0
  190. package/dist/server/src/api/plugins/proxy.plugin.js +200 -0
  191. package/dist/server/src/api/plugins/proxy.plugin.js.map +1 -0
  192. package/dist/server/src/api/routes/cameras.routes.js +56 -30
  193. package/dist/server/src/api/routes/cameras.routes.js.map +1 -1
  194. package/dist/server/src/api/routes/plugins.routes.js +65 -63
  195. package/dist/server/src/api/routes/plugins.routes.js.map +1 -1
  196. package/dist/server/src/api/routes/system.routes.js +7 -1
  197. package/dist/server/src/api/routes/system.routes.js.map +1 -1
  198. package/dist/server/src/api/routes/users.routes.js +8 -8
  199. package/dist/server/src/api/routes/users.routes.js.map +1 -1
  200. package/dist/server/src/api/schemas/backup.schema.d.ts +3 -3
  201. package/dist/server/src/api/schemas/backup.schema.js +1 -1
  202. package/dist/server/src/api/schemas/backup.schema.js.map +1 -1
  203. package/dist/server/src/api/schemas/cameras.schema.d.ts +1413 -529
  204. package/dist/server/src/api/schemas/cameras.schema.js +228 -182
  205. package/dist/server/src/api/schemas/cameras.schema.js.map +1 -1
  206. package/dist/server/src/api/schemas/config.schema.d.ts +29 -41
  207. package/dist/server/src/api/schemas/config.schema.js +10 -21
  208. package/dist/server/src/api/schemas/config.schema.js.map +1 -1
  209. package/dist/server/src/api/schemas/go2rtc.schema.d.ts +194 -162
  210. package/dist/server/src/api/schemas/go2rtc.schema.js +33 -58
  211. package/dist/server/src/api/schemas/go2rtc.schema.js.map +1 -1
  212. package/dist/server/src/api/schemas/plugins.schema.d.ts +17 -17
  213. package/dist/server/src/api/schemas/plugins.schema.js +1 -1
  214. package/dist/server/src/api/schemas/plugins.schema.js.map +1 -1
  215. package/dist/server/src/api/schemas/storage.schema.d.ts +22 -0
  216. package/dist/server/src/api/schemas/storage.schema.js +5 -0
  217. package/dist/server/src/api/schemas/storage.schema.js.map +1 -0
  218. package/dist/server/src/api/schemas/system.schema.d.ts +171 -3
  219. package/dist/server/src/api/schemas/system.schema.js +30 -3
  220. package/dist/server/src/api/schemas/system.schema.js.map +1 -1
  221. package/dist/server/src/api/schemas/users.schema.d.ts +98 -254
  222. package/dist/server/src/api/schemas/users.schema.js +6 -6
  223. package/dist/server/src/api/schemas/users.schema.js.map +1 -1
  224. package/dist/server/src/api/services/auth.service.d.ts +5 -5
  225. package/dist/server/src/api/services/auth.service.js +26 -35
  226. package/dist/server/src/api/services/auth.service.js.map +1 -1
  227. package/dist/server/src/api/services/cameras.service.d.ts +11 -16
  228. package/dist/server/src/api/services/cameras.service.js +143 -310
  229. package/dist/server/src/api/services/cameras.service.js.map +1 -1
  230. package/dist/server/src/api/services/plugins.service.d.ts +3 -1
  231. package/dist/server/src/api/services/plugins.service.js +48 -50
  232. package/dist/server/src/api/services/plugins.service.js.map +1 -1
  233. package/dist/server/src/api/services/users.service.d.ts +1 -0
  234. package/dist/server/src/api/services/users.service.js +20 -14
  235. package/dist/server/src/api/services/users.service.js.map +1 -1
  236. package/dist/server/src/api/types/index.d.ts +57 -46
  237. package/dist/server/src/api/types/index.js +0 -4
  238. package/dist/server/src/api/types/index.js.map +1 -1
  239. package/dist/server/src/api/utils/cert.d.ts +5 -1
  240. package/dist/server/src/api/utils/cert.js +24 -26
  241. package/dist/server/src/api/utils/cert.js.map +1 -1
  242. package/dist/server/src/api/utils/constants.d.ts +4 -2
  243. package/dist/server/src/api/utils/constants.js +4 -2
  244. package/dist/server/src/api/utils/constants.js.map +1 -1
  245. package/dist/server/src/api/utils/fetch.d.ts +1 -1
  246. package/dist/server/src/api/utils/fetch.js +2 -2
  247. package/dist/server/src/api/utils/fetch.js.map +1 -1
  248. package/dist/server/src/api/websocket/index.d.ts +1 -0
  249. package/dist/server/src/api/websocket/index.js +14 -9
  250. package/dist/server/src/api/websocket/index.js.map +1 -1
  251. package/dist/server/src/api/websocket/nsp/logs.d.ts +10 -2
  252. package/dist/server/src/api/websocket/nsp/logs.js +75 -27
  253. package/dist/server/src/api/websocket/nsp/logs.js.map +1 -1
  254. package/dist/server/src/api/websocket/nsp/metrics.d.ts +20 -12
  255. package/dist/server/src/api/websocket/nsp/metrics.js +188 -117
  256. package/dist/server/src/api/websocket/nsp/metrics.js.map +1 -1
  257. package/dist/server/src/api/websocket/nsp/plugins.d.ts +1 -1
  258. package/dist/server/src/api/websocket/nsp/plugins.js +3 -5
  259. package/dist/server/src/api/websocket/nsp/plugins.js.map +1 -1
  260. package/dist/server/src/api/websocket/nsp/server.js +6 -0
  261. package/dist/server/src/api/websocket/nsp/server.js.map +1 -1
  262. package/dist/server/src/api/websocket/types.d.ts +4 -2
  263. package/dist/server/src/api.d.ts +3 -4
  264. package/dist/server/src/api.js +13 -13
  265. package/dist/server/src/api.js.map +1 -1
  266. package/dist/server/src/camera/classes.d.ts +2 -0
  267. package/dist/server/src/camera/classes.js +24 -0
  268. package/dist/server/src/camera/classes.js.map +1 -0
  269. package/dist/server/src/camera/controller.d.ts +30 -18
  270. package/dist/server/src/camera/controller.js +236 -202
  271. package/dist/server/src/camera/controller.js.map +1 -1
  272. package/dist/server/src/camera/device.d.ts +34 -0
  273. package/dist/server/src/camera/device.js +327 -0
  274. package/dist/server/src/camera/device.js.map +1 -0
  275. package/dist/server/src/camera/frameWorker.d.ts +32 -31
  276. package/dist/server/src/camera/frameWorker.js +257 -247
  277. package/dist/server/src/camera/frameWorker.js.map +1 -1
  278. package/dist/server/src/camera/index.d.ts +92 -0
  279. package/dist/server/src/camera/index.js +531 -0
  280. package/dist/server/src/camera/index.js.map +1 -0
  281. package/dist/server/src/camera/interfaces.d.ts +17 -0
  282. package/dist/server/src/camera/interfaces.js +99 -0
  283. package/dist/server/src/camera/interfaces.js.map +1 -0
  284. package/dist/server/src/camera/iou.d.ts +2 -0
  285. package/dist/server/src/camera/iou.js +123 -0
  286. package/dist/server/src/camera/iou.js.map +1 -0
  287. package/dist/server/src/camera/polygon.d.ts +4 -0
  288. package/dist/server/src/camera/polygon.js +192 -0
  289. package/dist/server/src/camera/polygon.js.map +1 -0
  290. package/dist/server/src/camera/python/__init__.py +0 -0
  291. package/dist/server/src/camera/python/classes.py +41 -0
  292. package/dist/server/src/camera/python/interfaces.py +130 -0
  293. package/dist/server/src/camera/python/iou.py +158 -0
  294. package/dist/server/src/camera/python/polygon.py +230 -0
  295. package/dist/server/src/camera/python/typings.py +50 -0
  296. package/dist/server/src/camera/python/video_frame.py +143 -0
  297. package/dist/server/src/camera/session.d.ts +37 -0
  298. package/dist/server/src/camera/session.js +160 -0
  299. package/dist/server/src/camera/session.js.map +1 -0
  300. package/dist/server/src/camera/streaming/fmp4-session.d.ts +17 -0
  301. package/dist/server/src/camera/streaming/fmp4-session.js +308 -0
  302. package/dist/server/src/camera/streaming/fmp4-session.js.map +1 -0
  303. package/dist/server/src/camera/streaming/peer-connection.d.ts +26 -0
  304. package/dist/server/src/camera/streaming/peer-connection.js +213 -0
  305. package/dist/server/src/camera/streaming/peer-connection.js.map +1 -0
  306. package/dist/server/src/camera/streaming/rtsp-session.d.ts +19 -0
  307. package/dist/server/src/camera/streaming/rtsp-session.js +253 -0
  308. package/dist/server/src/camera/streaming/rtsp-session.js.map +1 -0
  309. package/dist/server/src/camera/streaming/webrtc-connection.d.ts +44 -0
  310. package/dist/server/src/camera/streaming/webrtc-connection.js +177 -0
  311. package/dist/server/src/camera/streaming/webrtc-connection.js.map +1 -0
  312. package/dist/server/src/camera/streaming/werift-session.d.ts +19 -0
  313. package/dist/server/src/camera/streaming/werift-session.js +246 -0
  314. package/dist/server/src/camera/streaming/werift-session.js.map +1 -0
  315. package/dist/server/src/camera/types.d.ts +16 -10
  316. package/dist/server/src/camera/utils.d.ts +9 -0
  317. package/dist/server/src/camera/utils.js +416 -0
  318. package/dist/server/src/camera/utils.js.map +1 -0
  319. package/dist/server/src/camera/videoFrame.d.ts +18 -0
  320. package/dist/server/src/camera/videoFrame.js +88 -0
  321. package/dist/server/src/camera/videoFrame.js.map +1 -0
  322. package/dist/server/src/cloud/index.d.ts +12 -0
  323. package/dist/server/src/cloud/index.js +49 -0
  324. package/dist/server/src/cloud/index.js.map +1 -0
  325. package/dist/server/src/cloud/remote/cloudflare.d.ts +7 -0
  326. package/dist/server/src/cloud/remote/cloudflare.js +12 -0
  327. package/dist/server/src/cloud/remote/cloudflare.js.map +1 -0
  328. package/dist/server/src/cloud/remote/upnp.d.ts +7 -0
  329. package/dist/server/src/cloud/remote/upnp.js +12 -0
  330. package/dist/server/src/cloud/remote/upnp.js.map +1 -0
  331. package/dist/server/src/cloud/remote/utils.d.ts +3 -0
  332. package/dist/server/src/cloud/remote/utils.js +20 -0
  333. package/dist/server/src/cloud/remote/utils.js.map +1 -0
  334. package/dist/server/src/cloud/types.d.ts +15 -0
  335. package/dist/server/src/cloud/types.js +11 -0
  336. package/dist/server/src/cloud/types.js.map +1 -0
  337. package/dist/server/src/decoder/child.d.ts +1 -0
  338. package/dist/server/src/decoder/child.js +749 -0
  339. package/dist/server/src/decoder/child.js.map +1 -0
  340. package/dist/server/src/decoder/imageUtils.d.ts +22 -0
  341. package/dist/server/src/decoder/imageUtils.js +196 -0
  342. package/dist/server/src/decoder/imageUtils.js.map +1 -0
  343. package/dist/server/src/decoder/manager.d.ts +19 -0
  344. package/dist/server/src/decoder/manager.js +208 -0
  345. package/dist/server/src/decoder/manager.js.map +1 -0
  346. package/dist/server/src/decoder/python/__init__.py +0 -0
  347. package/dist/server/src/decoder/python/child.py +903 -0
  348. package/dist/server/src/decoder/python/image_utils.py +196 -0
  349. package/dist/server/src/decoder/python/pool.py +45 -0
  350. package/dist/server/src/decoder/python/typings.py +57 -0
  351. package/dist/server/src/decoder/python/utils.py +70 -0
  352. package/dist/server/src/decoder/types.d.ts +23 -0
  353. package/dist/server/src/decoder/types.js.map +1 -0
  354. package/dist/server/src/decoder/utils.d.ts +13 -0
  355. package/dist/server/src/decoder/utils.js +45 -0
  356. package/dist/server/src/decoder/utils.js.map +1 -0
  357. package/dist/server/src/decoder/wasm/build/decoder.d.ts +43 -0
  358. package/dist/server/src/decoder/wasm/build/decoder.js +108 -0
  359. package/dist/server/src/decoder/wasm/build/decoder.wasm +0 -0
  360. package/dist/server/src/decoder/worker.d.ts +1 -0
  361. package/dist/server/src/decoder/worker.js +79 -0
  362. package/dist/server/src/decoder/worker.js.map +1 -0
  363. package/dist/server/src/go2rtc/index.d.ts +1 -0
  364. package/dist/server/src/go2rtc/index.js +27 -9
  365. package/dist/server/src/go2rtc/index.js.map +1 -1
  366. package/dist/server/src/go2rtc/types.d.ts +5 -4
  367. package/dist/server/src/go2rtc/types.js +6 -2
  368. package/dist/server/src/go2rtc/types.js.map +1 -1
  369. package/dist/server/src/main.js +19 -5
  370. package/dist/server/src/main.js.map +1 -1
  371. package/dist/server/src/manager/coreManager.d.ts +16 -0
  372. package/dist/server/src/manager/coreManager.js +95 -0
  373. package/dist/server/src/manager/coreManager.js.map +1 -0
  374. package/dist/server/src/manager/deviceManager.d.ts +12 -0
  375. package/dist/server/src/manager/deviceManager.js +130 -0
  376. package/dist/server/src/manager/deviceManager.js.map +1 -0
  377. package/dist/server/src/manager/types.d.ts +15 -0
  378. package/dist/server/src/manager/types.js +2 -0
  379. package/dist/server/src/manager/types.js.map +1 -0
  380. package/dist/server/src/plugins/index.d.ts +3 -1
  381. package/dist/server/src/plugins/index.js +42 -21
  382. package/dist/server/src/plugins/index.js.map +1 -1
  383. package/dist/server/src/plugins/plugin.d.ts +3 -3
  384. package/dist/server/src/plugins/plugin.js +13 -20
  385. package/dist/server/src/plugins/plugin.js.map +1 -1
  386. package/dist/server/src/plugins/runtime/base.d.ts +54 -0
  387. package/dist/server/src/plugins/runtime/base.js +223 -0
  388. package/dist/server/src/plugins/runtime/base.js.map +1 -0
  389. package/dist/server/src/plugins/runtime/index.d.ts +5 -0
  390. package/dist/server/src/plugins/runtime/index.js +13 -0
  391. package/dist/server/src/plugins/runtime/index.js.map +1 -0
  392. package/dist/server/src/plugins/runtime/node/child.d.ts +22 -0
  393. package/dist/server/src/plugins/runtime/node/child.js +152 -0
  394. package/dist/server/src/plugins/runtime/node/child.js.map +1 -0
  395. package/dist/server/src/plugins/runtime/node/index.d.ts +7 -0
  396. package/dist/server/src/plugins/runtime/node/index.js +54 -0
  397. package/dist/server/src/plugins/runtime/node/index.js.map +1 -0
  398. package/dist/server/src/plugins/runtime/node/plugin.d.ts +24 -0
  399. package/dist/server/src/plugins/runtime/node/plugin.js +128 -0
  400. package/dist/server/src/plugins/runtime/node/plugin.js.map +1 -0
  401. package/dist/server/src/plugins/runtime/node/pluginApi.d.ts +16 -0
  402. package/dist/server/src/plugins/runtime/node/pluginApi.js +18 -0
  403. package/dist/server/src/plugins/runtime/node/pluginApi.js.map +1 -0
  404. package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.d.ts +25 -0
  405. package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.js +230 -0
  406. package/dist/server/src/plugins/runtime/node/proxy/cameraDevice.js.map +1 -0
  407. package/dist/server/src/plugins/runtime/node/proxy/coreManager.d.ts +16 -0
  408. package/dist/server/src/plugins/runtime/node/proxy/coreManager.js +98 -0
  409. package/dist/server/src/plugins/runtime/node/proxy/coreManager.js.map +1 -0
  410. package/dist/server/src/plugins/runtime/node/proxy/deviceManager.d.ts +19 -0
  411. package/dist/server/src/plugins/runtime/node/proxy/deviceManager.js +144 -0
  412. package/dist/server/src/plugins/runtime/node/proxy/deviceManager.js.map +1 -0
  413. package/dist/server/src/plugins/runtime/node/storage.d.ts +34 -0
  414. package/dist/server/src/plugins/runtime/node/storage.js +313 -0
  415. package/dist/server/src/plugins/runtime/node/storage.js.map +1 -0
  416. package/dist/server/src/plugins/runtime/node/storageController.d.ts +18 -0
  417. package/dist/server/src/plugins/runtime/node/storageController.js +67 -0
  418. package/dist/server/src/plugins/runtime/node/storageController.js.map +1 -0
  419. package/dist/server/src/plugins/runtime/python/__init__.py +0 -0
  420. package/dist/server/src/plugins/runtime/python/child.py +248 -0
  421. package/dist/server/src/plugins/runtime/python/index.d.ts +9 -0
  422. package/dist/server/src/plugins/runtime/python/index.js +57 -0
  423. package/dist/server/src/plugins/runtime/python/index.js.map +1 -0
  424. package/dist/server/src/plugins/runtime/python/namespaces.py +101 -0
  425. package/dist/server/src/plugins/runtime/python/plugin.py +155 -0
  426. package/dist/server/src/plugins/runtime/python/plugin_api.py +29 -0
  427. package/dist/server/src/plugins/runtime/python/proxy/camera_device.py +1732 -0
  428. package/dist/server/src/plugins/runtime/python/proxy/core_manager.py +126 -0
  429. package/dist/server/src/plugins/runtime/python/proxy/device_manager.py +197 -0
  430. package/dist/server/src/plugins/runtime/python/schema.py +99 -0
  431. package/dist/server/src/plugins/runtime/python/storage.py +353 -0
  432. package/dist/server/src/plugins/runtime/python/storage_controller.py +102 -0
  433. package/dist/server/src/plugins/runtime/python/typings.py +195 -0
  434. package/dist/server/src/plugins/schema.d.ts +27 -34
  435. package/dist/server/src/plugins/schema.js +358 -369
  436. package/dist/server/src/plugins/schema.js.map +1 -1
  437. package/dist/server/src/plugins/types.d.ts +43 -1
  438. package/dist/server/src/plugins/types.js +16 -0
  439. package/dist/server/src/plugins/types.js.map +1 -1
  440. package/dist/server/src/plugins/worker.d.ts +12 -31
  441. package/dist/server/src/plugins/worker.js +89 -343
  442. package/dist/server/src/plugins/worker.js.map +1 -1
  443. package/dist/server/src/rpc/index.d.ts +32 -0
  444. package/dist/server/src/rpc/index.js +103 -0
  445. package/dist/server/src/rpc/index.js.map +1 -0
  446. package/dist/server/src/rpc/namespaces.d.ts +35 -0
  447. package/dist/server/src/rpc/namespaces.js +42 -0
  448. package/dist/server/src/rpc/namespaces.js.map +1 -0
  449. package/dist/server/src/{nats → rpc}/server.d.ts +6 -2
  450. package/dist/server/src/{nats → rpc}/server.js +76 -55
  451. package/dist/server/src/rpc/server.js.map +1 -0
  452. package/dist/server/src/rpc/types.d.ts +111 -0
  453. package/dist/server/src/rpc/types.js +2 -0
  454. package/dist/server/src/{nats → rpc}/types.js.map +1 -1
  455. package/dist/server/src/{nats → rpc}/utils.d.ts +1 -1
  456. package/dist/server/src/rpc/utils.js.map +1 -0
  457. package/dist/server/src/services/config/constants.js +12 -48
  458. package/dist/server/src/services/config/constants.js.map +1 -1
  459. package/dist/server/src/services/config/defaults.d.ts +12 -0
  460. package/dist/server/src/services/config/defaults.js +55 -0
  461. package/dist/server/src/services/config/defaults.js.map +1 -0
  462. package/dist/server/src/services/config/index.d.ts +57 -9
  463. package/dist/server/src/services/config/index.js +277 -130
  464. package/dist/server/src/services/config/index.js.map +1 -1
  465. package/dist/server/src/services/config/types.d.ts +10 -4
  466. package/dist/server/src/types.d.ts +3 -0
  467. package/dist/server/src/utils/path.d.ts +5 -0
  468. package/dist/server/src/utils/path.js +12 -0
  469. package/dist/server/src/utils/path.js.map +1 -0
  470. package/dist/server/src/utils/pythonInstaller.d.ts +46 -0
  471. package/dist/server/src/utils/pythonInstaller.js +463 -0
  472. package/dist/server/src/utils/pythonInstaller.js.map +1 -0
  473. package/package.json +57 -45
  474. package/types/fastify.d.ts +14 -0
  475. package/dist/interface/@intlify.Do1-T-x0.0.0.49.js +0 -15
  476. package/dist/interface/@mdi.CbjpODVZ.0.0.49.js +0 -1
  477. package/dist/interface/@tanstack.CgZ4BVuY.0.0.49.js +0 -1
  478. package/dist/interface/@vue.DeX8WChi.0.0.49.js +0 -17
  479. package/dist/interface/@vueform.WCJNykTK.0.0.49.js +0 -1
  480. package/dist/interface/@vueuse.fmA4o7MO.0.0.49.js +0 -1
  481. package/dist/interface/Account.D_hgF7as.0.0.49.js +0 -1
  482. package/dist/interface/Adminpanel.Cr2ysRnk.0.0.49.js +0 -2
  483. package/dist/interface/Appearance.DJPnnakw.0.0.49.js +0 -1
  484. package/dist/interface/Backup.DWrnTw65.0.0.49.js +0 -1
  485. package/dist/interface/Camera.Cm8bv5Jw.0.0.49.js +0 -1
  486. package/dist/interface/Cameras.BdMnnB_B.0.0.49.js +0 -1
  487. package/dist/interface/Camview.CvyTACeS.0.0.49.js +0 -1
  488. package/dist/interface/Config.R58trs6R.0.0.49.js +0 -1
  489. package/dist/interface/Console.ByS6OcfG.0.0.49.js +0 -4
  490. package/dist/interface/FirstSteps.BSZVBND8.0.0.49.js +0 -1
  491. package/dist/interface/NewCamera.CpKY8-_z.0.0.49.js +0 -469
  492. package/dist/interface/Plugin.ucDXXC6d.0.0.49.js +0 -1
  493. package/dist/interface/Plugins.Bl6Yy3fd.0.0.49.js +0 -1
  494. package/dist/interface/Recordings.Bm-_HDqk.0.0.49.js +0 -1
  495. package/dist/interface/Recordings.CVFqRJTQ.0.0.49.js +0 -1
  496. package/dist/interface/Settings.ClbXnv3j.0.0.49.js +0 -1
  497. package/dist/interface/System.BE0hX95Q.0.0.49.js +0 -4
  498. package/dist/interface/User.Ih1R_8u4.0.0.49.js +0 -1
  499. package/dist/interface/VConfigEditor.vue_vue_type_script_setup_true_lang.CAHg6HiL.0.0.49.js +0 -2
  500. package/dist/interface/VConsole.B9yVZ89i.0.0.49.js +0 -1
  501. package/dist/interface/VPlayer.DWJVzwuw.0.0.49.js +0 -4
  502. package/dist/interface/VPluginCard.pJNHjHpP.0.0.49.js +0 -4
  503. package/dist/interface/ace-builds.S1varnlI.0.0.49.js +0 -970
  504. package/dist/interface/apexcharts.BQn4Fbzn.0.0.49.js +0 -838
  505. package/dist/interface/assets/@vueform.0.0.49.CroAHJs8.css +0 -1
  506. package/dist/interface/assets/@xterm.0.0.49.CFbL2ovg.css +0 -32
  507. package/dist/interface/assets/Account.0.0.49.Bnw6Lbtd.css +0 -1
  508. package/dist/interface/assets/Adminpanel.0.0.49.a3t1v3MB.css +0 -1
  509. package/dist/interface/assets/Camera.0.0.49.Br9s6-lM.css +0 -1
  510. package/dist/interface/assets/Cameras.0.0.49.Buf1Dgce.css +0 -1
  511. package/dist/interface/assets/Camview.0.0.49.B7Cja2ry.css +0 -1
  512. package/dist/interface/assets/Config.0.0.49.DNGo2krN.css +0 -1
  513. package/dist/interface/assets/Console.0.0.49.Bh8l9QnM.css +0 -1
  514. package/dist/interface/assets/FirstSteps.0.0.49.Mu8VPl13.css +0 -1
  515. package/dist/interface/assets/NewCamera.0.0.49.DtjxW0Pf.css +0 -1
  516. package/dist/interface/assets/Plugin.0.0.49.YIpAU1_n.css +0 -1
  517. package/dist/interface/assets/Plugins.0.0.49.DXSoO9M1.css +0 -1
  518. package/dist/interface/assets/Settings.0.0.49.CVmui2kE.css +0 -1
  519. package/dist/interface/assets/User.0.0.49.BiGtIFqt.css +0 -1
  520. package/dist/interface/assets/VConsole.0.0.49.BCqKHpmJ.css +0 -1
  521. package/dist/interface/assets/VPlayer.0.0.49.C4lm2rVR.css +0 -1
  522. package/dist/interface/assets/VPluginCard.0.0.49.C8Lj6X-J.css +0 -1
  523. package/dist/interface/assets/main.0.0.49.OJngntGT.css +0 -1
  524. package/dist/interface/assets/vue3-toastify.0.0.49.DHXAGmwn.css +0 -1
  525. package/dist/interface/assets/vuetify.0.0.49.Dua9WSqa.css +0 -5
  526. package/dist/interface/axios.DIsA03vz.0.0.49.js +0 -6
  527. package/dist/interface/backup.DO02r0Uq.0.0.49.js +0 -1
  528. package/dist/interface/dnd-core.De50QAoi.0.0.49.js +0 -1
  529. package/dist/interface/engine.io-client.BkCVneko.0.0.49.js +0 -1
  530. package/dist/interface/fast-deep-equal.Cba0yG7P.0.0.49.js +0 -1
  531. package/dist/interface/fonts/Inter/Inter-Regular.ttf +0 -0
  532. package/dist/interface/highlight.js.B_E0LW5C.0.0.49.js +0 -2
  533. package/dist/interface/hookable.B8xFkYCm.0.0.49.js +0 -1
  534. package/dist/interface/linkify-it.B6s2BWlj.0.0.49.js +0 -1
  535. package/dist/interface/main.BBe3SGhH.0.0.49.js +0 -4
  536. package/dist/interface/perfect-debounce.Cp2ysxOb.0.0.49.js +0 -1
  537. package/dist/interface/pinia.ggULzsrQ.0.0.49.js +0 -5
  538. package/dist/interface/plugins.D11FBqVV.0.0.49.js +0 -1
  539. package/dist/interface/react-dnd-touch-backend.Bu6wFEmw.0.0.49.js +0 -1
  540. package/dist/interface/rxjs.BoFuGUYG.0.0.49.js +0 -3
  541. package/dist/interface/socket.io-client.DkEQDv7C.0.0.49.js +0 -1
  542. package/dist/interface/socket.io-parser.DIURoCw8.0.0.49.js +0 -1
  543. package/dist/interface/system.D_LabhBl.0.0.49.js +0 -1
  544. package/dist/interface/types.Cz9TaZAP.0.0.49.js +0 -1
  545. package/dist/interface/utils.mAKpSMLY.0.0.49.js +0 -1
  546. package/dist/interface/uuid.Ch9TGLTe.0.0.49.js +0 -1
  547. package/dist/interface/vee-validate.8pUAwQ7T.0.0.49.js +0 -5
  548. package/dist/interface/vue-i18n.CBqdKRmG.0.0.49.js +0 -5
  549. package/dist/interface/vue-inline-svg.ZWpe_tFT.0.0.49.js +0 -1
  550. package/dist/interface/vue-router.DvFvaoP2.0.0.49.js +0 -5
  551. package/dist/interface/vue3-apexcharts.BHSDC9pf.0.0.49.js +0 -1
  552. package/dist/interface/vue3-dnd.DbCy3Qbj.0.0.49.js +0 -1
  553. package/dist/interface/vue3-toastify.JJyrPHKk.0.0.49.js +0 -1
  554. package/dist/interface/vuetify.kkqUjVJA.0.0.49.js +0 -5
  555. package/dist/interface/zod.bkdEMpUp.0.0.49.js +0 -1
  556. package/dist/server/src/api/utils/cameraSource.d.ts +0 -6
  557. package/dist/server/src/api/utils/cameraSource.js +0 -51
  558. package/dist/server/src/api/utils/cameraSource.js.map +0 -1
  559. package/dist/server/src/api/websocket/go2rtc.d.ts +0 -21
  560. package/dist/server/src/api/websocket/go2rtc.js +0 -88
  561. package/dist/server/src/api/websocket/go2rtc.js.map +0 -1
  562. package/dist/server/src/api/websocket/nsp/proxy.d.ts +0 -27
  563. package/dist/server/src/api/websocket/nsp/proxy.js +0 -127
  564. package/dist/server/src/api/websocket/nsp/proxy.js.map +0 -1
  565. package/dist/server/src/nats/index.d.ts +0 -40
  566. package/dist/server/src/nats/index.js +0 -164
  567. package/dist/server/src/nats/index.js.map +0 -1
  568. package/dist/server/src/nats/proxy/cameraDevice.d.ts +0 -22
  569. package/dist/server/src/nats/proxy/cameraDevice.js +0 -249
  570. package/dist/server/src/nats/proxy/cameraDevice.js.map +0 -1
  571. package/dist/server/src/nats/proxy/coreManager.d.ts +0 -14
  572. package/dist/server/src/nats/proxy/coreManager.js +0 -68
  573. package/dist/server/src/nats/proxy/coreManager.js.map +0 -1
  574. package/dist/server/src/nats/proxy/deviceManager.d.ts +0 -14
  575. package/dist/server/src/nats/proxy/deviceManager.js +0 -101
  576. package/dist/server/src/nats/proxy/deviceManager.js.map +0 -1
  577. package/dist/server/src/nats/server.js.map +0 -1
  578. package/dist/server/src/nats/types.d.ts +0 -18
  579. package/dist/server/src/nats/utils.js.map +0 -1
  580. /package/dist/interface/assets/{Backup.0.0.49.CX0rT0QJ.css → SettingsBackup.CX0rT0QJ.0.0.50-internal.1.css} +0 -0
  581. /package/dist/interface/assets/{highlight.0.0.49.Ch2EwETz.css → highlight.Ch2EwETz.0.0.50-internal.1.css} +0 -0
  582. /package/dist/interface/assets/{logo-256.0.0.49.BCQk9H1-.png → logo-256.BCQk9H1-.0.0.50-internal.1.png} +0 -0
  583. /package/dist/interface/assets/{logo-512.0.0.49.DLKVOU2S.png → logo-512.DLKVOU2S.0.0.50-internal.1.png} +0 -0
  584. /package/dist/interface/assets/{logo.0.0.49.DmEiRk0z.png → logo.DmEiRk0z.0.0.50-internal.1.png} +0 -0
  585. /package/dist/interface/assets/{mode-json.0.0.49.Br7xisR1.js → mode-json.Br7xisR1.0.0.50-internal.1.js} +0 -0
  586. /package/dist/interface/assets/{mode-yaml.0.0.49.CIYL8U3d.js → mode-yaml.CIYL8U3d.0.0.50-internal.1.js} +0 -0
  587. /package/dist/interface/{@babel.l0sNRNKZ.0.0.49.js → js/@babel.l0sNRNKZ.0.0.50-internal.1.js} +0 -0
  588. /package/dist/interface/{@react-dnd.CcwRs9xb.0.0.49.js → js/@react-dnd.CcwRs9xb.0.0.50-internal.1.js} +0 -0
  589. /package/dist/interface/{@socket.io.Dkula2eQ.0.0.49.js → js/@socket.io.Dkula2eQ.0.0.50-internal.1.js} +0 -0
  590. /package/dist/interface/{birpc.l0sNRNKZ.0.0.49.js → js/birpc.l0sNRNKZ.0.0.50-internal.1.js} +0 -0
  591. /package/dist/interface/{compare-versions.DqEOhma6.0.0.49.js → js/compare-versions.DqEOhma6.0.0.50-internal.1.js} +0 -0
  592. /package/dist/interface/{dijkstrajs.C00ieaqj.0.0.49.js → js/dijkstrajs.C00ieaqj.0.0.50-internal.1.js} +0 -0
  593. /package/dist/interface/{engine.io-parser.BiEtp6m2.0.0.49.js → js/engine.io-parser.BiEtp6m2.0.0.50-internal.1.js} +0 -0
  594. /package/dist/interface/{entities.C20TfXL6.0.0.49.js → js/entities.C20TfXL6.0.0.50-internal.1.js} +0 -0
  595. /package/dist/interface/{ev-emitter.X5f1qa-c.0.0.49.js → js/ev-emitter.X5f1qa-c.0.0.50-internal.1.js} +0 -0
  596. /package/dist/interface/{get-size.D1dS-IaP.0.0.49.js → js/get-size.D1dS-IaP.0.0.50-internal.1.js} +0 -0
  597. /package/dist/interface/{vue.l0sNRNKZ.0.0.49.js → js/hookable.l0sNRNKZ.0.0.50-internal.1.js} +0 -0
  598. /package/dist/interface/{mdurl.k9Sl0PQj.0.0.49.js → js/mdurl.k9Sl0PQj.0.0.50-internal.1.js} +0 -0
  599. /package/dist/interface/{punycode.js.Dj65hjkv.0.0.49.js → js/punycode.js.Dj65hjkv.0.0.50-internal.1.js} +0 -0
  600. /package/dist/interface/{react-dnd-html5-backend.1HQjlkwI.0.0.49.js → js/react-dnd-html5-backend.1HQjlkwI.0.0.50-internal.1.js} +0 -0
  601. /package/dist/interface/{redux.BFxtlG_c.0.0.49.js → js/redux.BFxtlG_c.0.0.50-internal.1.js} +0 -0
  602. /package/dist/interface/{tslib.9k7AwCpt.0.0.49.js → js/tslib.9k7AwCpt.0.0.50-internal.1.js} +0 -0
  603. /package/dist/interface/{uc.micro.kMc2yuuw.0.0.49.js → js/uc.micro.kMc2yuuw.0.0.50-internal.1.js} +0 -0
  604. /package/dist/server/src/{nats → decoder}/types.js +0 -0
  605. /package/dist/server/src/{nats → rpc}/utils.js +0 -0
@@ -0,0 +1,903 @@
1
+ import asyncio
2
+ import os
3
+ import re
4
+ import sys
5
+ from collections.abc import AsyncGenerator
6
+ from dataclasses import dataclass
7
+ from datetime import datetime
8
+ from typing import Any, Literal, Optional, Union, cast
9
+
10
+ import setproctitle
11
+
12
+ from _camera_ui_tools.camera_ui_common import LoggerService, SignalHandler
13
+ from _camera_ui_tools.camera_ui_rpc_client import ClientInstance
14
+ from _camera_ui_tools.camera_ui_rpc_client.utils.rpc import rpc
15
+ from _camera_ui_tools.camera_ui_types import (
16
+ CameraFrameWorkerDecoder,
17
+ CameraFrameWorkerResolution,
18
+ DecoderFormat,
19
+ FfmpegArgs,
20
+ FrameBuffer,
21
+ FrameData,
22
+ FrameMetadata,
23
+ ImageInformation,
24
+ ImageOptions,
25
+ ImageOutputFormat,
26
+ )
27
+ from decoder.python.image_utils import process_image_threaded
28
+ from decoder.python.typings import (
29
+ BaseFrameWorkerConfig,
30
+ FrameWorkerInterface,
31
+ PixelFormat,
32
+ WorkerToMainMessage,
33
+ )
34
+ from decoder.python.utils import TCPConnectionDetails, create_single_connection_server
35
+ from plugins.runtime.python.namespaces import FrameWorkerCoreManagerNamespaces, NamespaceManager
36
+ from plugins.runtime.python.typings import CoreManagerInterface
37
+
38
+ process_name = (
39
+ sys.argv[2] if len(sys.argv) > 2 else sys.argv[1] if len(sys.argv) > 1 else "camera.ui - Frame Worker"
40
+ )
41
+ setproctitle.setproctitle(process_name)
42
+
43
+ PIXEL_FORMAT: PixelFormat = "yuv420p"
44
+ METADATA_REGEX = r"s:\s*(\d+x\d+)"
45
+
46
+
47
+ @dataclass
48
+ class Frame:
49
+ data: bytes
50
+ timestamp: int
51
+ metadata: FrameMetadata
52
+
53
+
54
+ class FrameConsumer:
55
+ def __init__(self, consumer_id: int, stream: "FFmpegStream") -> None:
56
+ self.id: int = consumer_id
57
+ self.stream: FFmpegStream = stream
58
+ self.last_frame_timestamp: int = 0
59
+ self.resolve_new_frame_future: Optional[asyncio.Future[None]] = None
60
+
61
+ def notify_new_frame(self) -> None:
62
+ if self.resolve_new_frame_future and not self.resolve_new_frame_future.done():
63
+ self.resolve_new_frame_future.set_result(None)
64
+ self.resolve_new_frame_future = None
65
+
66
+ async def wait_for_new_frame(self) -> None:
67
+ if self.resolve_new_frame_future is None or self.resolve_new_frame_future.done():
68
+ self.resolve_new_frame_future = asyncio.Future()
69
+ await self.resolve_new_frame_future
70
+
71
+ def __aiter__(self) -> "FrameConsumer":
72
+ return self
73
+
74
+ async def __anext__(self) -> Frame:
75
+ while True:
76
+ frame = self.stream.get_next_frame(self.last_frame_timestamp)
77
+
78
+ if frame:
79
+ self.last_frame_timestamp = frame.timestamp
80
+ return frame
81
+
82
+ if not self.stream.stream_active:
83
+ raise StopAsyncIteration
84
+
85
+ # Wait for notification of new frame
86
+ await self.wait_for_new_frame()
87
+
88
+
89
+ class FFmpegStream:
90
+ def __init__(self, worker: "FrameWorkerChild"):
91
+ self.worker = worker
92
+
93
+ width, height = map(int, worker.config["resolution"].split("x"))
94
+ self.width = width
95
+ self.height = height
96
+
97
+ # Process Management
98
+ self.ffmpeg_process: Optional[asyncio.subprocess.Process] = None
99
+ self.active_viewers = 0
100
+ self.ffmpeg_hw_options: Optional[FfmpegArgs] = None
101
+ self.server: Optional[TCPConnectionDetails] = None
102
+ self.socket: Optional[tuple[asyncio.StreamReader, asyncio.StreamWriter]] = None
103
+ self.exit_task: Optional[asyncio.Task[Any]] = None
104
+ self.frame_processing_task: Optional[asyncio.Task[Any]] = None
105
+ self.stderr_task: Optional[asyncio.Task[Any]] = None
106
+
107
+ # State
108
+ self.stream_active = False
109
+ self.metadata: Optional[FrameMetadata] = None
110
+ self.is_shutting_down = False
111
+ self.stream_start_timeout_sec = 60.0 # Timeout in Sekunden
112
+ self.initialization_task: Optional[asyncio.Task[Any]] = None
113
+
114
+ # Reconnection Logic
115
+ self.reconnect_count = 0
116
+
117
+ # Frame Queue Management
118
+ self.frame_buffer: list[Frame] = []
119
+ self.last_frame: Optional[Frame] = None
120
+ self.queue_consumers: set[FrameConsumer] = set()
121
+ self.frame_processing_active = False
122
+ self.buffer_duration_ms = 5000
123
+
124
+ # Health Check
125
+ self.health_check_task: Optional[asyncio.Task[Any]] = None
126
+ self.last_frame_timestamp = 0
127
+ self.health_check_time = 5.0
128
+ self.max_frame_time = 15.0
129
+
130
+ # Consumer management
131
+ self.next_consumer_id = 0
132
+
133
+ @property
134
+ def bytes_per_pixel(self) -> float:
135
+ if self.pixel_format == "rgb24":
136
+ return 3.0
137
+ elif self.pixel_format in ["yuv420p", "nv12"]:
138
+ return 1.5
139
+ return 1.5
140
+
141
+ @property
142
+ def pixel_format(self) -> PixelFormat:
143
+ return PIXEL_FORMAT
144
+
145
+ @property
146
+ def frame_size(self) -> int:
147
+ return int(self.width * self.height * self.bytes_per_pixel)
148
+
149
+ async def initialize(self) -> None:
150
+ if self.initialization_task:
151
+ await self.initialization_task
152
+ return
153
+
154
+ if self.stream_active:
155
+ return
156
+
157
+ try:
158
+ self.initialization_task = asyncio.create_task(self._start_stream_process())
159
+ await self.initialization_task
160
+ finally:
161
+ self.initialization_task = None
162
+
163
+ def close(self) -> None:
164
+ if not self.stream_active:
165
+ return
166
+
167
+ self.worker.logger.trace("Closing FFmpeg stream")
168
+ self.cleanup_resources()
169
+
170
+ def cleanup(self) -> None:
171
+ self.is_shutting_down = True
172
+ self.cleanup_resources()
173
+
174
+ def register_viewer(self) -> FrameConsumer:
175
+ self.active_viewers += 1
176
+ consumer = FrameConsumer(self.next_consumer_id, self)
177
+ self.next_consumer_id += 1
178
+ self.queue_consumers.add(consumer)
179
+ return consumer
180
+
181
+ def unregister_viewer(self, consumer: FrameConsumer) -> None:
182
+ self.queue_consumers.discard(consumer)
183
+ self.active_viewers -= 1
184
+ if self.active_viewers <= 0:
185
+ self.active_viewers = 0
186
+ self.close()
187
+
188
+ def get_next_frame(self, timestamp: int) -> Optional[Frame]:
189
+ if not self.last_frame or self.last_frame.timestamp <= timestamp:
190
+ return None
191
+
192
+ return Frame(
193
+ data=bytes(self.last_frame.data),
194
+ timestamp=self.last_frame.timestamp,
195
+ metadata=self.last_frame.metadata,
196
+ )
197
+
198
+ def get_frame_by_timestamp(self, timestamp: int, max_difference: int = 0) -> Optional[Frame]:
199
+ if not self.frame_buffer:
200
+ return None
201
+
202
+ # Quick boundary checks
203
+ first_frame = self.frame_buffer[0]
204
+ last_frame = self.frame_buffer[-1]
205
+
206
+ # Check if timestamp is outside our buffer range (plus max_difference)
207
+ if (
208
+ timestamp < first_frame.timestamp - max_difference
209
+ or timestamp > last_frame.timestamp + max_difference
210
+ ):
211
+ return None
212
+
213
+ # Binary search for closest frame
214
+ left = 0
215
+ right = len(self.frame_buffer) - 1
216
+
217
+ while left <= right:
218
+ mid = (left + right) // 2
219
+ frame = self.frame_buffer[mid]
220
+ diff = frame.timestamp - timestamp
221
+
222
+ # Exact match
223
+ if diff == 0:
224
+ return frame
225
+
226
+ if diff < 0:
227
+ left = mid + 1
228
+ else:
229
+ right = mid - 1
230
+
231
+ # If we need exact match only
232
+ if max_difference == 0:
233
+ return None
234
+
235
+ # Find closest frame within max_difference
236
+ # After binary search, 'left' points to the insertion point
237
+ # Check frames around this point
238
+ candidates = [
239
+ self.frame_buffer[max(0, left - 1)],
240
+ self.frame_buffer[min(len(self.frame_buffer) - 1, left)],
241
+ ]
242
+
243
+ best_match = None
244
+ smallest_diff = float("inf")
245
+
246
+ for frame in candidates:
247
+ diff = abs(frame.timestamp - timestamp)
248
+ if diff <= max_difference and diff < smallest_diff:
249
+ smallest_diff = diff
250
+ best_match = frame
251
+
252
+ if best_match:
253
+ return Frame(
254
+ data=bytes(best_match.data), timestamp=best_match.timestamp, metadata=best_match.metadata
255
+ )
256
+
257
+ return None
258
+
259
+ async def _start_stream_process(self) -> None:
260
+ try:
261
+ await self._launch_stream()
262
+ self.reconnect_count = 0
263
+ except Exception as error:
264
+ if self.is_shutting_down or self.active_viewers == 0:
265
+ return
266
+
267
+ self.reconnect_count = min(self.reconnect_count + 1, 10)
268
+ delay_sec = self._calculate_reconnect_delay_sec()
269
+
270
+ self.worker.logger.warn(f"Connection failed, retrying in {delay_sec}s")
271
+ self.worker.logger.debug(f"Error: {str(error)}")
272
+
273
+ await asyncio.sleep(delay_sec)
274
+ self.worker.logger.debug("Retrying connection...")
275
+ return await self._start_stream_process()
276
+
277
+ async def _launch_stream(self) -> None:
278
+ if self.active_viewers == 0:
279
+ self.worker.logger.debug("No active consumers, not starting stream")
280
+ return
281
+
282
+ self.cleanup_resources()
283
+
284
+ self.server = await create_single_connection_server("127.0.0.1", {"limit": self.frame_size * 10})
285
+
286
+ ffmpeg_arguments = await self._prepare_ffmpeg_arguments(self.server.server_url)
287
+ self.worker.logger.trace(
288
+ f"Starting FFmpeg with args: {self.worker.config['ffmpegPath']} {' '.join(ffmpeg_arguments)}"
289
+ )
290
+
291
+ self.ffmpeg_process = await asyncio.create_subprocess_exec(
292
+ self.worker.config["ffmpegPath"],
293
+ *ffmpeg_arguments,
294
+ stdin=asyncio.subprocess.DEVNULL,
295
+ stdout=asyncio.subprocess.DEVNULL,
296
+ stderr=asyncio.subprocess.PIPE,
297
+ )
298
+
299
+ self.exit_task = asyncio.create_task(self._on_ffmpeg_exit())
300
+
301
+ try:
302
+ reader, writer = await self.server.connection_promise
303
+ self.socket = (reader, writer)
304
+ self.metadata = await self._extract_metadata()
305
+ self.stream_active = True
306
+ self.frame_processing_task = asyncio.create_task(self._process_frames())
307
+ self._start_health_check()
308
+
309
+ except Exception as error:
310
+ self.cleanup_resources()
311
+ raise error
312
+
313
+ async def _on_ffmpeg_exit(self) -> None:
314
+ if not self.ffmpeg_process:
315
+ return
316
+
317
+ await self.ffmpeg_process.wait()
318
+ if self.active_viewers > 0 and not self.is_shutting_down:
319
+ self.worker.logger.warn("FFmpeg process exited unexpectedly, restarting in 10 seconds...")
320
+ self.cleanup_resources()
321
+ await asyncio.sleep(10)
322
+ await self.initialize()
323
+ else:
324
+ self.worker.logger.debug("FFmpeg process exited")
325
+
326
+ def _start_health_check(self) -> None:
327
+ if self.health_check_task:
328
+ self.health_check_task.cancel()
329
+
330
+ async def health_check_loop() -> None:
331
+ while self.stream_active and not self.is_shutting_down:
332
+ await asyncio.sleep(self.health_check_time)
333
+
334
+ if self.active_viewers == 0:
335
+ continue
336
+
337
+ now = int(datetime.now().timestamp() * 1000)
338
+ time_since_last_frame_sec = (now - self.last_frame_timestamp) / 1000
339
+
340
+ # If no frames for 30 seconds and we have active viewers, restart
341
+ if (
342
+ self.last_frame_timestamp > 0
343
+ and time_since_last_frame_sec > self.max_frame_time
344
+ and self.active_viewers > 0
345
+ ):
346
+ self.worker.logger.warn(
347
+ f"No frames received in {time_since_last_frame_sec:.1f}s! This may be due to a network issue, FFmpeg failure or high load on the system."
348
+ )
349
+ self.worker.logger.log("Restarting...")
350
+ self.cleanup_resources()
351
+ asyncio.create_task(self.initialize())
352
+ break
353
+
354
+ self.health_check_task = asyncio.create_task(health_check_loop())
355
+
356
+ async def _process_frames(self) -> None:
357
+ if self.frame_processing_active or not self.socket or not self.metadata:
358
+ return
359
+
360
+ first_chunk_received = False
361
+ first_frame_received = False
362
+ self.frame_processing_active = True
363
+ reader, _ = self.socket
364
+ metadata = self.metadata
365
+ buffer = bytearray()
366
+ last_buffer_size = 0
367
+
368
+ try:
369
+ while True:
370
+ chunk = await reader.read(8192)
371
+
372
+ if not self.frame_processing_active:
373
+ break
374
+
375
+ if not chunk:
376
+ continue
377
+
378
+ if len(buffer) > self.frame_size * 10:
379
+ self.worker.logger.warn(
380
+ f"Buffer growing: {len(buffer)} Bytes "
381
+ f"({len(buffer) / metadata['frameSize']:.2f} frames)"
382
+ )
383
+
384
+ if not first_chunk_received:
385
+ self.worker.logger.trace("First chunk received")
386
+ first_chunk_received = True
387
+
388
+ buffer.extend(chunk)
389
+
390
+ while len(buffer) >= self.frame_size:
391
+ frame_data = bytes(buffer[: self.frame_size])
392
+ buffer = buffer[self.frame_size :]
393
+
394
+ if last_buffer_size == len(buffer) and len(buffer) > 0:
395
+ self.worker.logger.warn(
396
+ f"Possible issue: Buffer size not changing: {len(buffer)} bytes"
397
+ )
398
+ # buffer = bytearray()
399
+ break
400
+
401
+ last_buffer_size = len(buffer)
402
+
403
+ if not first_frame_received:
404
+ self.worker.logger.trace("First frame received")
405
+ first_frame_received = True
406
+
407
+ self._add_frame_to_queue(frame_data, self.metadata)
408
+ except Exception as error:
409
+ self.worker.logger.error(f"Error in frame processing: {str(error)}")
410
+ finally:
411
+ self.frame_processing_active = False
412
+
413
+ def _add_frame_to_queue(self, frame_data: bytes, metadata: FrameMetadata) -> None:
414
+ timestamp = int(datetime.now().timestamp() * 1000)
415
+ self.last_frame_timestamp = timestamp
416
+
417
+ new_frame = Frame(data=frame_data, timestamp=timestamp, metadata=metadata)
418
+
419
+ self.frame_buffer.append(new_frame)
420
+ self.last_frame = new_frame
421
+
422
+ self._cleanup_old_frames()
423
+
424
+ for consumer in self.queue_consumers:
425
+ consumer.notify_new_frame()
426
+
427
+ def _cleanup_old_frames(self) -> None:
428
+ current_time = int(datetime.now().timestamp() * 1000)
429
+ buffer_threshold = current_time - self.buffer_duration_ms
430
+
431
+ while len(self.frame_buffer) > 1 and self.frame_buffer[0].timestamp < buffer_threshold:
432
+ self.frame_buffer.pop(0)
433
+
434
+ async def _extract_metadata(self) -> FrameMetadata:
435
+ if not self.ffmpeg_process or not self.ffmpeg_process.stderr:
436
+ raise RuntimeError("FFmpeg process not started or stderr not available")
437
+
438
+ metadata_future: asyncio.Future[FrameMetadata] = asyncio.Future()
439
+
440
+ async def read_stderr() -> None:
441
+ try:
442
+ assert self.ffmpeg_process and self.ffmpeg_process.stderr
443
+
444
+ async for line in self.ffmpeg_process.stderr:
445
+ if not metadata_future.done() and line:
446
+ metadata = self._parse_metadata_from_stderr(line)
447
+ if metadata:
448
+ self.worker.logger.debug(f"Metadata received: {metadata}")
449
+ metadata_future.set_result(metadata)
450
+ except Exception as e:
451
+ if not metadata_future.done():
452
+ metadata_future.set_exception(e)
453
+
454
+ self.stderr_task = asyncio.create_task(read_stderr())
455
+
456
+ try:
457
+ return await asyncio.wait_for(metadata_future, self.stream_start_timeout_sec)
458
+ except asyncio.TimeoutError as e:
459
+ raise TimeoutError("FFmpeg stream start timeout") from e
460
+
461
+ def _calculate_reconnect_delay_sec(self) -> float:
462
+ if self.reconnect_count == 10:
463
+ return 60.0
464
+ else:
465
+ return 10.0
466
+
467
+ def _parse_metadata_from_stderr(self, data: bytes) -> Optional[FrameMetadata]:
468
+ stderr_text = data.decode("utf-8", errors="replace")
469
+
470
+ match = re.search(METADATA_REGEX, stderr_text)
471
+ if not match:
472
+ return None
473
+
474
+ resolution = match.group(1)
475
+ original_width, original_height = map(int, resolution.split("x"))
476
+ frame_data_size = self.frame_size
477
+
478
+ metadata: FrameMetadata = {
479
+ "format": "nv12" if self.worker.config["decoder"] == "gpu" else "yuv420p",
480
+ "frameSize": frame_data_size,
481
+ "width": self.width,
482
+ "height": self.height,
483
+ "origHeight": original_height,
484
+ "origWidth": original_width,
485
+ }
486
+
487
+ return metadata
488
+
489
+ async def _prepare_ffmpeg_arguments(self, server_url: str) -> list[str]:
490
+ if not self.ffmpeg_hw_options:
491
+ core_manager = await self._create_core_manager_proxy()
492
+ self.ffmpeg_hw_options = (
493
+ await core_manager.getHwaccelInfo(
494
+ {
495
+ "targetCodec": "h264",
496
+ "keepOnHardware": True,
497
+ "pixelFormat": self.pixel_format,
498
+ "scale": {
499
+ "width": self.width,
500
+ "height": self.height,
501
+ },
502
+ }
503
+ )
504
+ )[0]
505
+
506
+ filter_chain = ["showinfo=checksum=0"] + self.ffmpeg_hw_options["hwaccelFilters"]
507
+ if self.worker.config["fps"] > 0:
508
+ filter_chain.append(f"fps=fps={self.worker.config['fps']}")
509
+
510
+ return [
511
+ "-hide_banner",
512
+ *self.ffmpeg_hw_options["hwaccelArgs"],
513
+ "-fflags",
514
+ "+discardcorrupt+flush_packets+nobuffer",
515
+ "-flags",
516
+ "low_delay",
517
+ "-analyzeduration",
518
+ "0",
519
+ "-probesize",
520
+ "500000",
521
+ "-reorder_queue_size",
522
+ "0",
523
+ "-user_agent",
524
+ "camera.ui/frameworker",
525
+ "-timeout",
526
+ "5000000",
527
+ "-rtsp_transport",
528
+ "tcp",
529
+ "-re",
530
+ "-i",
531
+ self.worker.config["cameraSource"],
532
+ *self.ffmpeg_hw_options["hwDeviceArgs"],
533
+ "-fps_mode",
534
+ "cfr",
535
+ "-vf",
536
+ ",".join(filter_chain),
537
+ "-an",
538
+ "-dn",
539
+ "-sn",
540
+ "-f",
541
+ "rawvideo",
542
+ f"{server_url}?tcp_nodelay=1",
543
+ ]
544
+
545
+ def cleanup_resources(self) -> None:
546
+ self.stream_active = False
547
+ self.metadata = None
548
+ self.frame_processing_active = False
549
+
550
+ if self.health_check_task:
551
+ self.health_check_task.cancel()
552
+ self.health_check_task = None
553
+
554
+ if self.exit_task:
555
+ self.exit_task.cancel()
556
+ self.exit_task = None
557
+
558
+ if self.frame_processing_task:
559
+ self.frame_processing_task.cancel()
560
+ self.frame_processing_task = None
561
+
562
+ if self.stderr_task:
563
+ self.stderr_task.cancel()
564
+ self.stderr_task = None
565
+
566
+ if self.server:
567
+ self.server.terminate()
568
+ self.server = None
569
+
570
+ if self.socket:
571
+ _, writer = self.socket
572
+ writer.close()
573
+ self.socket = None
574
+
575
+ if self.ffmpeg_process:
576
+ try:
577
+ self.ffmpeg_process.kill()
578
+ self.ffmpeg_process = None
579
+ except Exception:
580
+ pass
581
+
582
+ async def _create_core_manager_proxy(self) -> CoreManagerInterface:
583
+ return await self.worker.create_rpc_proxy(
584
+ CoreManagerInterface, self.worker.namespaces["coreManagerRpc"]
585
+ )
586
+
587
+
588
+ class FrameWorkerChild(ClientInstance, FrameWorkerInterface):
589
+ def __init__(self) -> None:
590
+ super().__init__(
591
+ "service",
592
+ {
593
+ "endpoints": os.environ["PROXY_ENDPOINTS"].split(","),
594
+ "auth": {"user": os.environ["PROXY_USER"], "password": os.environ["PROXY_PASSWORD"]},
595
+ "tls": {
596
+ "cert": os.environ["PROXY_CERT"],
597
+ "key": os.environ["PROXY_KEY"],
598
+ "ca": os.environ["PROXY_CA"],
599
+ },
600
+ "metadata": {
601
+ "id": NamespaceManager.frame_worker_namespaces(os.environ["CAMERA_ID"])[
602
+ "frameWorkerChild"
603
+ ],
604
+ "name": "Frame Worker",
605
+ },
606
+ "bundled_connection": False,
607
+ },
608
+ )
609
+
610
+ self.namespaces: FrameWorkerCoreManagerNamespaces = {
611
+ **NamespaceManager.frame_worker_namespaces(os.environ["CAMERA_ID"]),
612
+ **NamespaceManager.core_manager_namespaces(),
613
+ }
614
+
615
+ self.config: BaseFrameWorkerConfig = {
616
+ "cameraId": os.environ["CAMERA_ID"],
617
+ "cameraName": os.environ["CAMERA_NAME"],
618
+ "cameraSource": os.environ["CAMERA_SOURCE"],
619
+ "ffmpegPath": os.environ["FFMPEG_PATH"],
620
+ "auth": {"user": os.environ["PROXY_USER"], "password": os.environ["PROXY_PASSWORD"]},
621
+ "proxyEndpoints": os.environ["PROXY_ENDPOINTS"].split(","),
622
+ "fps": int(os.environ["FPS"]),
623
+ "resolution": cast(CameraFrameWorkerResolution, os.environ["RESOLUTION"]),
624
+ "decoder": cast(CameraFrameWorkerDecoder, os.environ["DECODER"]),
625
+ }
626
+
627
+ for key in ["PROXY_USER", "PROXY_PASSWORD", "PROXY_ENDPOINTS", "PROXY_CERT", "PROXY_KEY", "PROXY_CA"]:
628
+ if key in os.environ:
629
+ del os.environ[key]
630
+
631
+ self.logger = LoggerService(
632
+ {
633
+ "prefix": "Frame Worker",
634
+ "suffix": self.config["cameraName"],
635
+ "disable_timestamps": os.environ.get("LOGGER_DISABLE_TIMESTAMPS") == "1",
636
+ "debug_enabled": os.environ.get("LOGGER_LEVEL") in ["debug", "trace"],
637
+ "trace_enabled": os.environ.get("LOGGER_LEVEL") == "trace",
638
+ }
639
+ )
640
+
641
+ self.ffmpeg_stream = FFmpegStream(self)
642
+
643
+ self.signal_handler = SignalHandler(
644
+ {
645
+ "display_name": "[Signal]",
646
+ "timeout_duration": 1000,
647
+ "logger": self.logger,
648
+ "close_function": self._close,
649
+ }
650
+ )
651
+
652
+ self.stopped = False
653
+
654
+ async def run(self) -> None:
655
+ try:
656
+ self.signal_handler.setup_handlers()
657
+ await self.start()
658
+ await self.signal_handler.shutdown_event.wait()
659
+ except asyncio.CancelledError:
660
+ pass
661
+ finally:
662
+ await self._close()
663
+
664
+ async def on_start(self) -> None:
665
+ await self.register_rpc_handler(self.namespaces["frameWorkerChildRpc"], self)
666
+ await self._send_message({"message": "started", "data": {}})
667
+
668
+ async def on_before_stop(self) -> None:
669
+ return await self._close()
670
+
671
+ async def on_stop(self) -> None:
672
+ pass
673
+
674
+ @rpc(public=True)
675
+ async def generateFrames(self, options: Optional[ImageOptions] = None) -> AsyncGenerator[FrameData, None]:
676
+ consumer = None
677
+
678
+ try:
679
+ consumer = self.ffmpeg_stream.register_viewer()
680
+ await self.ffmpeg_stream.initialize()
681
+
682
+ if not self.ffmpeg_stream.metadata:
683
+ raise RuntimeError("Stream-Metadaten nicht verfügbar")
684
+
685
+ metadata = self.ffmpeg_stream.metadata
686
+
687
+ async for frame in consumer:
688
+ validated_options = self._validate_options(metadata, options)
689
+
690
+ if validated_options:
691
+ processed_frame = await self.processFrame(
692
+ frame.data,
693
+ metadata["width"],
694
+ metadata["height"],
695
+ metadata["format"],
696
+ validated_options,
697
+ )
698
+
699
+ yield {
700
+ "data": processed_frame["image"],
701
+ "metadata": metadata,
702
+ "timestamp": frame.timestamp,
703
+ "info": processed_frame["info"],
704
+ }
705
+ else:
706
+ info = self._get_image_information(
707
+ metadata["width"], metadata["height"], metadata["format"]
708
+ )
709
+
710
+ yield {
711
+ "data": frame.data,
712
+ "metadata": metadata,
713
+ "timestamp": frame.timestamp,
714
+ "info": info,
715
+ }
716
+ except Exception as error:
717
+ self.logger.error(f"Error in frame generation: {error}")
718
+ finally:
719
+ if consumer:
720
+ self.ffmpeg_stream.unregister_viewer(consumer)
721
+
722
+ @rpc(public=True)
723
+ async def getPrebufferedFrame(
724
+ self,
725
+ timestamp: int,
726
+ options: Optional[ImageOptions] = None,
727
+ max_difference: int = 500,
728
+ ) -> Optional[FrameData]:
729
+ prebuffered_frame = self.ffmpeg_stream.get_frame_by_timestamp(timestamp, max_difference)
730
+ if not prebuffered_frame:
731
+ self.logger.debug(f"No prebuffered frame found for timestamp {timestamp}")
732
+ return None
733
+
734
+ validated_options = options and self._validate_options(prebuffered_frame.metadata, options)
735
+
736
+ if validated_options:
737
+ processed_frame = await self.processFrame(
738
+ prebuffered_frame.data,
739
+ prebuffered_frame.metadata["width"],
740
+ prebuffered_frame.metadata["height"],
741
+ prebuffered_frame.metadata["format"],
742
+ validated_options,
743
+ )
744
+
745
+ return {
746
+ "data": processed_frame["image"],
747
+ "metadata": prebuffered_frame.metadata,
748
+ "timestamp": prebuffered_frame.timestamp,
749
+ "info": processed_frame["info"],
750
+ }
751
+ else:
752
+ info = self._get_image_information(
753
+ prebuffered_frame.metadata["width"],
754
+ prebuffered_frame.metadata["height"],
755
+ prebuffered_frame.metadata["format"],
756
+ )
757
+
758
+ return {
759
+ "data": prebuffered_frame.data,
760
+ "metadata": prebuffered_frame.metadata,
761
+ "timestamp": prebuffered_frame.timestamp,
762
+ "info": info,
763
+ }
764
+
765
+ @rpc(public=True)
766
+ async def processFrame(
767
+ self,
768
+ frame: bytes,
769
+ width: int,
770
+ height: int,
771
+ format: Union[DecoderFormat, Literal["rgba"], Literal["gray"]],
772
+ options: ImageOptions,
773
+ ) -> FrameBuffer:
774
+ new_frame = frame if isinstance(frame, bytes) else bytes(frame)
775
+ info = self._get_image_information(width, height, format, options)
776
+
777
+ image = await process_image_threaded(new_frame, width, height, format, options)
778
+
779
+ return {"image": image, "info": info}
780
+
781
+ def _validate_options(
782
+ self, metadata: FrameMetadata, options: Optional[ImageOptions] = None
783
+ ) -> Optional[ImageOptions]:
784
+ if not options:
785
+ return None
786
+
787
+ validated: ImageOptions = {}
788
+
789
+ # Format conversion
790
+ metadata_format = "rgb" if metadata["format"] == "rgb24" else metadata["format"]
791
+
792
+ if "format" in options and "to" in options["format"] and options["format"]["to"] != metadata_format:
793
+ validated["format"] = options["format"]
794
+
795
+ # Cropping
796
+ if "crop" in options:
797
+ crop = options["crop"]
798
+ left = crop.get("left", 0)
799
+ top = crop.get("top", 0)
800
+
801
+ # Validate crop parameters
802
+ if left >= metadata["width"] or top >= metadata["height"]:
803
+ return None
804
+
805
+ width = min(crop.get("width", metadata["width"]), metadata["width"] - left)
806
+ height = min(crop.get("height", metadata["height"]), metadata["height"] - top)
807
+
808
+ if width <= 0 or height <= 0:
809
+ return None
810
+
811
+ # Skip full frame "crops"
812
+ if not (left == 0 and top == 0 and width == metadata["width"] and height == metadata["height"]):
813
+ validated["crop"] = {"left": left, "top": top, "width": width, "height": height}
814
+
815
+ # Resizing
816
+ if "resize" in options:
817
+ resize = options["resize"]
818
+ target_width = resize.get("width", 0)
819
+ target_height = resize.get("height", 0)
820
+
821
+ # Handle negative values (which mean "use original")
822
+ if target_width < 0:
823
+ target_width = metadata["width"]
824
+ if target_height < 0:
825
+ target_height = metadata["height"]
826
+
827
+ # Calculate missing dimension if only one is provided
828
+ if target_width > 0 and target_height == 0:
829
+ target_height = round((target_width * metadata["height"]) / metadata["width"])
830
+ elif target_height > 0 and target_width == 0:
831
+ target_width = round((target_height * metadata["width"]) / metadata["height"])
832
+
833
+ # Skip if no resize needed
834
+ if not (
835
+ (target_width == 0 and target_height == 0)
836
+ or (target_width == metadata["width"] and target_height == metadata["height"])
837
+ ):
838
+ validated["resize"] = {"width": target_width, "height": target_height}
839
+
840
+ # Return None if no transformations are needed
841
+ return validated if validated else None
842
+
843
+ def _get_image_information(
844
+ self,
845
+ input_width: int,
846
+ input_height: int,
847
+ input_format: Union[DecoderFormat, Literal["rgba"], Literal["gray"]],
848
+ options: Optional[ImageOptions] = None,
849
+ ) -> ImageInformation:
850
+ # Calculate output width
851
+ width = input_width
852
+ if options and "resize" in options and options["resize"].get("width"):
853
+ width = options["resize"]["width"]
854
+ elif options and "crop" in options:
855
+ crop = options["crop"]
856
+ left = crop.get("left", 0)
857
+ crop_width = crop.get("width", input_width)
858
+ width = min(crop_width, input_width - left)
859
+
860
+ # Calculate output height
861
+ height = input_height
862
+ if options and "resize" in options and options["resize"].get("height"):
863
+ height = options["resize"]["height"]
864
+ elif options and "crop" in options:
865
+ crop = options["crop"]
866
+ top = crop.get("top", 0)
867
+ crop_height = crop.get("height", input_height)
868
+ height = min(crop_height, input_height - top)
869
+
870
+ # Determine output format
871
+ format: Union[DecoderFormat, ImageOutputFormat] = input_format
872
+ if options and "format" in options and "to" in options["format"]:
873
+ format = options["format"]["to"]
874
+
875
+ format = "rgb" if format == "rgb24" else format
876
+
877
+ # Calculate channels based on format
878
+ channels = 1.5
879
+
880
+ if format == "rgba":
881
+ channels = 4
882
+ elif format == "rgb":
883
+ channels = 3
884
+ elif format == "gray":
885
+ channels = 1
886
+
887
+ return {"width": width, "height": height, "channels": channels, "format": format}
888
+
889
+ async def _send_message(self, message: WorkerToMainMessage) -> None:
890
+ await self.send_to_server(message)
891
+
892
+ async def _close(self) -> None:
893
+ if self.stopped:
894
+ return
895
+
896
+ self.stopped = True
897
+ self.ffmpeg_stream.cleanup()
898
+ await self.stop()
899
+
900
+
901
+ if __name__ == "__main__":
902
+ worker = FrameWorkerChild()
903
+ asyncio.run(worker.run())