@camera.ui/server 0.0.50-internal.0 → 0.0.50-internal.2

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 (390) hide show
  1. package/dist/interface/index.html +44 -44
  2. package/dist/interface/js/{@primevue.OhxoO3MD.0.0.50-internal.0.js → @primevue.BAIU_p3r.0.0.50-internal.2.js} +1 -1
  3. package/dist/interface/js/{@tanstack.D1IL6eOv.0.0.50-internal.0.js → @tanstack.mdCorqzE.0.0.50-internal.2.js} +1 -1
  4. package/dist/interface/js/{@vee-validate.BGPyWWTh.0.0.50-internal.0.js → @vee-validate.D0vsSsly.0.0.50-internal.2.js} +1 -1
  5. package/dist/interface/js/{@vueuse.BsKtqdiG.0.0.50-internal.0.js → @vueuse.we5ZpWr2.0.0.50-internal.2.js} +1 -1
  6. package/dist/interface/js/{Adminpanel.D93Kvbwp.0.0.50-internal.0.js → Adminpanel.9AEBJ3H1.0.0.50-internal.2.js} +1 -1
  7. package/dist/interface/js/{Camera.DF2l3OMA.0.0.50-internal.0.js → Camera.CZcnEH0C.0.0.50-internal.2.js} +1 -1
  8. package/dist/interface/js/{Cameras.YzvZccdv.0.0.50-internal.0.js → Cameras.DE0LkcGu.0.0.50-internal.2.js} +2 -2
  9. package/dist/interface/js/Cammesh.CVvmkelB.0.0.50-internal.2.js +1 -0
  10. package/dist/interface/js/{Camview.CB7_HnoQ.0.0.50-internal.0.js → Camview.CUr4pGoU.0.0.50-internal.2.js} +1 -1
  11. package/dist/interface/js/{Config.BwflsWTm.0.0.50-internal.0.js → Config.CaJhu4fF.0.0.50-internal.2.js} +2 -2
  12. package/dist/interface/js/{Console.DZM8pN8Q.0.0.50-internal.0.js → Console.5VUmgryj.0.0.50-internal.2.js} +1 -1
  13. package/dist/interface/js/{CuiConsole.BXXU7Gth.0.0.50-internal.0.js → CuiConsole.iYmUxAR5.0.0.50-internal.2.js} +1 -1
  14. package/dist/interface/js/{CuiPluginCard.YFOrpbVD.0.0.50-internal.0.js → CuiPluginCard.DXPyE5mF.0.0.50-internal.2.js} +1 -1
  15. package/dist/interface/js/{CuiTimeline.VV5KSJd5.0.0.50-internal.0.js → CuiTimeline.BqtlOFnV.0.0.50-internal.2.js} +1 -1
  16. package/dist/interface/js/{FirstSteps.b-nvymgb.0.0.50-internal.0.js → FirstSteps.C_RI-SDQ.0.0.50-internal.2.js} +1 -1
  17. package/dist/interface/js/{Plugin.BOMpVEwM.0.0.50-internal.0.js → Plugin.Ch_v02eN.0.0.50-internal.2.js} +1 -1
  18. package/dist/interface/js/{Plugins.DdPwaUDA.0.0.50-internal.0.js → Plugins.BpXAYgSG.0.0.50-internal.2.js} +1 -1
  19. package/dist/interface/js/Recordings.CIKHJytH.0.0.50-internal.2.js +1 -0
  20. package/dist/interface/js/{Settings.D24ttaPu.0.0.50-internal.0.js → Settings.BcLoGNEy.0.0.50-internal.2.js} +1 -1
  21. package/dist/interface/js/{SettingsAccount.ms3aqz4E.0.0.50-internal.0.js → SettingsAccount.DMROW8kx.0.0.50-internal.2.js} +1 -1
  22. package/dist/interface/js/SettingsAppearance.CUaHpihp.0.0.50-internal.2.js +1 -0
  23. package/dist/interface/js/{SettingsAppearance.vue_vue_type_script_setup_true_lang.CBQ6lL3T.0.0.50-internal.0.js → SettingsAppearance.vue_vue_type_script_setup_true_lang.BuKZ-Uco.0.0.50-internal.2.js} +1 -1
  24. package/dist/interface/js/{SettingsBackup.BPEc4Rjg.0.0.50-internal.0.js → SettingsBackup.0QdwFSpv.0.0.50-internal.2.js} +1 -1
  25. package/dist/interface/js/SettingsRecordings.B-aj0U8_.0.0.50-internal.2.js +1 -0
  26. package/dist/interface/js/{SettingsRemote.BL5nXbUT.0.0.50-internal.0.js → SettingsRemote.Bi1YAJ76.0.0.50-internal.2.js} +1 -1
  27. package/dist/interface/js/{SettingsSystem.D7T0AIpm.0.0.50-internal.0.js → SettingsSystem.CAx66Iir.0.0.50-internal.2.js} +1 -1
  28. package/dist/interface/js/{SettingsUsers.1u0vCOVG.0.0.50-internal.0.js → SettingsUsers.CQcDtGy1.0.0.50-internal.2.js} +1 -1
  29. package/dist/interface/js/{VersionsHandler.vue_vue_type_script_setup_true_lang.xDishkkS.0.0.50-internal.0.js → VersionsHandler.vue_vue_type_script_setup_true_lang.BhXMzIhV.0.0.50-internal.2.js} +1 -1
  30. package/dist/interface/js/{ace-builds.D1nmvCwb.0.0.50-internal.0.js → ace-builds.C0sCXSu5.0.0.50-internal.2.js} +2 -2
  31. package/dist/interface/js/{ace.config.G96T2z54.0.0.50-internal.0.js → ace.config.DNqPWa0Q.0.0.50-internal.2.js} +1 -1
  32. package/dist/interface/js/{backup.B_Gzxtp_.0.0.50-internal.0.js → backup.DAXgG3bP.0.0.50-internal.2.js} +1 -1
  33. package/dist/interface/js/{chart.js.CP_nMnnf.0.0.50-internal.0.js → chart.js.Bq3YocRX.0.0.50-internal.2.js} +1 -1
  34. package/dist/interface/js/{close-circle.DYLuVIOg.0.0.50-internal.0.js → close-circle.9rxyNw0z.0.0.50-internal.2.js} +1 -1
  35. package/dist/interface/js/{dnd-core.T9OeW7mu.0.0.50-internal.0.js → dnd-core.BuEvHAsS.0.0.50-internal.2.js} +1 -1
  36. package/dist/interface/js/{draggabilly.D3zGcBb3.0.0.50-internal.0.js → draggabilly.DUdE08x8.0.0.50-internal.2.js} +1 -1
  37. package/dist/interface/js/{engine.io-client.kITRnq-g.0.0.50-internal.0.js → engine.io-client.DWU6YI8o.0.0.50-internal.2.js} +1 -1
  38. package/dist/interface/js/{fast-deep-equal.Bpc9mIsj.0.0.50-internal.0.js → fast-deep-equal.BpPyC6E4.0.0.50-internal.2.js} +1 -1
  39. package/dist/interface/js/{highlight.js.BlSXU-Wb.0.0.50-internal.0.js → highlight.js.BoR2Rhdd.0.0.50-internal.2.js} +1 -1
  40. package/dist/interface/js/{linkify-it.C3N1lWsJ.0.0.50-internal.0.js → linkify-it.BXzPONHs.0.0.50-internal.2.js} +1 -1
  41. package/dist/interface/js/{main.D0YR3Jat.0.0.50-internal.0.js → main.DwcBYfWc.0.0.50-internal.2.js} +3 -3
  42. package/dist/interface/js/{markdown-it.Dj0dt5s2.0.0.50-internal.0.js → markdown-it.BUDVOjPt.0.0.50-internal.2.js} +1 -1
  43. package/dist/interface/js/{nprogress.BwQWDcGj.0.0.50-internal.0.js → nprogress.CsG-OBoI.0.0.50-internal.2.js} +1 -1
  44. package/dist/interface/js/{pinia.DRh7plEC.0.0.50-internal.0.js → pinia.CqEQao5R.0.0.50-internal.2.js} +1 -1
  45. package/dist/interface/js/{primevue.Cl58krXf.0.0.50-internal.0.js → primevue.D91sslRx.0.0.50-internal.2.js} +1 -1
  46. package/dist/interface/js/{qrcode.C1sDj6P8.0.0.50-internal.0.js → qrcode.SdSTPzZO.0.0.50-internal.2.js} +1 -1
  47. package/dist/interface/js/{react-dnd-touch-backend.BA4WhUJo.0.0.50-internal.0.js → react-dnd-touch-backend.BwroebQ4.0.0.50-internal.2.js} +1 -1
  48. package/dist/interface/js/{refresh-rounded.D_SmhhUf.0.0.50-internal.0.js → refresh-rounded.DxM48YSv.0.0.50-internal.2.js} +1 -1
  49. package/dist/interface/js/{rxjs.C-fTBwEO.0.0.50-internal.0.js → rxjs.Cmpbnzo4.0.0.50-internal.2.js} +1 -1
  50. package/dist/interface/js/{socket.io-client.DKrRxgjP.0.0.50-internal.0.js → socket.io-client.DF2YgZo1.0.0.50-internal.2.js} +1 -1
  51. package/dist/interface/js/{socket.io-parser.EXj3YDH2.0.0.50-internal.0.js → socket.io-parser.BUs2ineY.0.0.50-internal.2.js} +1 -1
  52. package/dist/interface/js/{system.CY8rGd-Q.0.0.50-internal.0.js → system.DmkT2LKx.0.0.50-internal.2.js} +1 -1
  53. package/dist/interface/js/{trash-fill.CMnCN3Oy.0.0.50-internal.0.js → trash-fill.dPzyZDVa.0.0.50-internal.2.js} +1 -1
  54. package/dist/interface/js/{unidragger.D0w6Tqtt.0.0.50-internal.0.js → unidragger.y2ZlFveS.0.0.50-internal.2.js} +1 -1
  55. package/dist/interface/js/{vee-validate.BeiObIH8.0.0.50-internal.0.js → vee-validate.Y-alCADW.0.0.50-internal.2.js} +1 -1
  56. package/dist/interface/js/{vue-chartjs.DtdZdiYw.0.0.50-internal.0.js → vue-chartjs.sRVFTqDf.0.0.50-internal.2.js} +1 -1
  57. package/dist/interface/js/{vue-i18n.BW2bx_6z.0.0.50-internal.0.js → vue-i18n.D5WrXOZa.0.0.50-internal.2.js} +1 -1
  58. package/dist/interface/js/{vue-inline-svg.BJkQGmKz.0.0.50-internal.0.js → vue-inline-svg.R0uz_abA.0.0.50-internal.2.js} +1 -1
  59. package/dist/interface/js/{vue-router.B2mOXHaC.0.0.50-internal.0.js → vue-router.65mnGy-o.0.0.50-internal.2.js} +1 -1
  60. package/dist/interface/js/{vue-zoomable.BKDyCJE7.0.0.50-internal.0.js → vue-zoomable.B1Qop6Uu.0.0.50-internal.2.js} +1 -1
  61. package/dist/interface/js/{vue3-dnd.DRK24CBp.0.0.50-internal.0.js → vue3-dnd.CwmyAcir.0.0.50-internal.2.js} +1 -1
  62. package/dist/interface/js/{zoom-out.DxvzgVEo.0.0.50-internal.0.js → zoom-out.CMPALvRh.0.0.50-internal.2.js} +1 -1
  63. package/dist/interface/sw.js +1 -1
  64. package/dist/server/package.json +1 -1
  65. package/dist/server/src/rpc/server.js +4 -1
  66. package/dist/server/src/rpc/server.js.map +1 -1
  67. package/package.json +1 -1
  68. package/.prettierignore +0 -12
  69. package/.prettierrc.json +0 -12
  70. package/artillery.yaml +0 -29
  71. package/bin/cameraui-server.ts +0 -11
  72. package/dist/interface/js/Cammesh.D-6dAROQ.0.0.50-internal.0.js +0 -1
  73. package/dist/interface/js/Recordings.DhxjIW7e.0.0.50-internal.0.js +0 -1
  74. package/dist/interface/js/SettingsAppearance.DsTjKXk1.0.0.50-internal.0.js +0 -1
  75. package/dist/interface/js/SettingsRecordings.DgW7M0jj.0.0.50-internal.0.js +0 -1
  76. package/eslint.config.js +0 -103
  77. package/localdeps.txt +0 -10
  78. package/mypy.ini +0 -30
  79. package/requirements.txt +0 -15
  80. package/ruff.toml +0 -90
  81. package/src/__init__.py +0 -0
  82. package/src/_camera_ui_tools/__init__.py +0 -0
  83. package/src/_camera_ui_tools/__pycache__/__init__.cpython-311.pyc +0 -0
  84. package/src/api/controllers/api.controller.ts +0 -19
  85. package/src/api/controllers/auth.controller.ts +0 -294
  86. package/src/api/controllers/backup.controller.ts +0 -72
  87. package/src/api/controllers/cameras.controller.ts +0 -1029
  88. package/src/api/controllers/config.controller.ts +0 -102
  89. package/src/api/controllers/files.controller.ts +0 -35
  90. package/src/api/controllers/frameWorkers.controller.ts +0 -109
  91. package/src/api/controllers/plugins.controller.ts +0 -1206
  92. package/src/api/controllers/system.controller.ts +0 -273
  93. package/src/api/controllers/users.controller.ts +0 -648
  94. package/src/api/database/checks.ts +0 -268
  95. package/src/api/database/constants.ts +0 -8
  96. package/src/api/database/index.ts +0 -262
  97. package/src/api/database/migration.ts +0 -62
  98. package/src/api/database/selfcheck.ts +0 -492
  99. package/src/api/database/types.ts +0 -104
  100. package/src/api/go2rtc/api/application.ts +0 -48
  101. package/src/api/go2rtc/api/config.ts +0 -61
  102. package/src/api/go2rtc/api/discover.ts +0 -197
  103. package/src/api/go2rtc/api/index.ts +0 -49
  104. package/src/api/go2rtc/api/snapshot.ts +0 -44
  105. package/src/api/go2rtc/api/streams.ts +0 -168
  106. package/src/api/go2rtc/index.ts +0 -43
  107. package/src/api/go2rtc/queue.ts +0 -50
  108. package/src/api/go2rtc/types.ts +0 -174
  109. package/src/api/index.ts +0 -286
  110. package/src/api/middlewares/authPermission.middleware.ts +0 -46
  111. package/src/api/middlewares/authValidation.middleware.ts +0 -160
  112. package/src/api/middlewares/pagination.middleware.ts +0 -67
  113. package/src/api/middlewares/socketAuth.middleware.ts +0 -136
  114. package/src/api/plugins/header.plugin.ts +0 -15
  115. package/src/api/plugins/logger.plugin.ts +0 -44
  116. package/src/api/plugins/proxy.plugin.ts +0 -255
  117. package/src/api/plugins/socket.plugin.ts +0 -28
  118. package/src/api/plugins/system.plugin.ts +0 -48
  119. package/src/api/plugins/useragent.plugin.ts +0 -19
  120. package/src/api/routes/api.routes.ts +0 -10
  121. package/src/api/routes/auth.routes.ts +0 -56
  122. package/src/api/routes/backup.routes.ts +0 -28
  123. package/src/api/routes/cameras.routes.ts +0 -281
  124. package/src/api/routes/config.routes.ts +0 -66
  125. package/src/api/routes/files.routes.ts +0 -15
  126. package/src/api/routes/frameWorkers.routes.ts +0 -39
  127. package/src/api/routes/index.ts +0 -37
  128. package/src/api/routes/plugins.routes.ts +0 -420
  129. package/src/api/routes/system.routes.ts +0 -101
  130. package/src/api/routes/users.routes.ts +0 -167
  131. package/src/api/schemas/backup.schema.ts +0 -112
  132. package/src/api/schemas/cameras.schema.ts +0 -479
  133. package/src/api/schemas/config.schema.ts +0 -38
  134. package/src/api/schemas/go2rtc.schema.ts +0 -189
  135. package/src/api/schemas/plugins.schema.ts +0 -126
  136. package/src/api/schemas/storage.schema.ts +0 -11
  137. package/src/api/schemas/system.schema.ts +0 -45
  138. package/src/api/schemas/users.schema.ts +0 -185
  139. package/src/api/services/auth.service.ts +0 -210
  140. package/src/api/services/backup.service.ts +0 -144
  141. package/src/api/services/cameras.service.ts +0 -671
  142. package/src/api/services/plugins.service.ts +0 -470
  143. package/src/api/services/system.service.ts +0 -85
  144. package/src/api/services/users.service.ts +0 -276
  145. package/src/api/types/index.ts +0 -675
  146. package/src/api/utils/cert.ts +0 -254
  147. package/src/api/utils/constants.ts +0 -17
  148. package/src/api/utils/fetch.ts +0 -21
  149. package/src/api/utils/moveFiles.ts +0 -45
  150. package/src/api/utils/parse.ts +0 -17
  151. package/src/api/websocket/index.ts +0 -110
  152. package/src/api/websocket/nsp/logs.ts +0 -240
  153. package/src/api/websocket/nsp/main.ts +0 -27
  154. package/src/api/websocket/nsp/metrics.ts +0 -301
  155. package/src/api/websocket/nsp/notifications.ts +0 -43
  156. package/src/api/websocket/nsp/plugins.ts +0 -37
  157. package/src/api/websocket/nsp/server.ts +0 -220
  158. package/src/api/websocket/nsp/status.ts +0 -77
  159. package/src/api/websocket/types.ts +0 -55
  160. package/src/api.ts +0 -163
  161. package/src/camera/classes.ts +0 -32
  162. package/src/camera/controller.ts +0 -579
  163. package/src/camera/device.ts +0 -422
  164. package/src/camera/frameWorker.ts +0 -403
  165. package/src/camera/index.ts +0 -679
  166. package/src/camera/interfaces.ts +0 -95
  167. package/src/camera/iou.ts +0 -153
  168. package/src/camera/polygon.ts +0 -226
  169. package/src/camera/python/__init__.py +0 -0
  170. package/src/camera/python/__pycache__/__init__.cpython-311.pyc +0 -0
  171. package/src/camera/python/__pycache__/classes.cpython-311.pyc +0 -0
  172. package/src/camera/python/__pycache__/delegate_controller.cpython-311.pyc +0 -0
  173. package/src/camera/python/__pycache__/interfaces.cpython-311.pyc +0 -0
  174. package/src/camera/python/__pycache__/iou.cpython-310.pyc +0 -0
  175. package/src/camera/python/__pycache__/iou.cpython-311.pyc +0 -0
  176. package/src/camera/python/__pycache__/iou2.cpython-310.pyc +0 -0
  177. package/src/camera/python/__pycache__/polygon.cpython-311.pyc +0 -0
  178. package/src/camera/python/__pycache__/typings.cpython-311.pyc +0 -0
  179. package/src/camera/python/__pycache__/video_frame.cpython-311.pyc +0 -0
  180. package/src/camera/python/classes.py +0 -41
  181. package/src/camera/python/interfaces.py +0 -130
  182. package/src/camera/python/iou.py +0 -158
  183. package/src/camera/python/polygon.py +0 -230
  184. package/src/camera/python/test/__pycache__/polygon.cpython-310.pyc +0 -0
  185. package/src/camera/python/test/iou_test.py +0 -799
  186. package/src/camera/python/test/polygon.py +0 -238
  187. package/src/camera/python/test/polygon_test.py +0 -256
  188. package/src/camera/python/test/polygon_test2.py +0 -484
  189. package/src/camera/python/typings.py +0 -50
  190. package/src/camera/python/video_frame.py +0 -143
  191. package/src/camera/session.ts +0 -192
  192. package/src/camera/streaming/fmp4-session.ts +0 -390
  193. package/src/camera/streaming/peer-connection.ts +0 -273
  194. package/src/camera/streaming/rtsp-session.ts +0 -331
  195. package/src/camera/streaming/webrtc-connection.ts +0 -260
  196. package/src/camera/streaming/werift-session.ts +0 -317
  197. package/src/camera/test/iou_test.ts +0 -761
  198. package/src/camera/test/polygon.test.ts +0 -611
  199. package/src/camera/test/polygon_test.ts +0 -210
  200. package/src/camera/types.ts +0 -48
  201. package/src/camera/utils.ts +0 -489
  202. package/src/camera/videoFrame.ts +0 -123
  203. package/src/cloud/index.ts +0 -61
  204. package/src/cloud/remote/cloudflare.ts +0 -18
  205. package/src/cloud/remote/upnp.ts +0 -18
  206. package/src/cloud/remote/utils.ts +0 -24
  207. package/src/cloud/types.ts +0 -16
  208. package/src/decoder/child.ts +0 -883
  209. package/src/decoder/imageUtils.ts +0 -275
  210. package/src/decoder/manager.ts +0 -251
  211. package/src/decoder/python/__init__.py +0 -0
  212. package/src/decoder/python/__pycache__/__init__.cpython-311.pyc +0 -0
  213. package/src/decoder/python/__pycache__/image_utils.cpython-311.pyc +0 -0
  214. package/src/decoder/python/__pycache__/typings.cpython-311.pyc +0 -0
  215. package/src/decoder/python/__pycache__/utils.cpython-311.pyc +0 -0
  216. package/src/decoder/python/child.py +0 -903
  217. package/src/decoder/python/image_utils.py +0 -196
  218. package/src/decoder/python/pool.py +0 -45
  219. package/src/decoder/python/test/group.py +0 -62
  220. package/src/decoder/python/test/motion.mp4 +0 -0
  221. package/src/decoder/python/test/motion2.mp4 +0 -0
  222. package/src/decoder/python/test/opencl.cl +0 -70
  223. package/src/decoder/python/test/opencl2.cl +0 -130
  224. package/src/decoder/python/test/test.py +0 -427
  225. package/src/decoder/python/test/test1.jpg +0 -0
  226. package/src/decoder/python/test/test1_resized.jpg +0 -0
  227. package/src/decoder/python/test/test2.jpg +0 -0
  228. package/src/decoder/python/test/test2.py +0 -451
  229. package/src/decoder/python/test/test2_resized.jpg +0 -0
  230. package/src/decoder/python/test/test3.jpg +0 -0
  231. package/src/decoder/python/test/utils.py +0 -50
  232. package/src/decoder/python/typings.py +0 -57
  233. package/src/decoder/python/utils.py +0 -70
  234. package/src/decoder/test/child.ts +0 -117
  235. package/src/decoder/test/ffmpeg.ts +0 -371
  236. package/src/decoder/test/test.ts +0 -182
  237. package/src/decoder/types.ts +0 -27
  238. package/src/decoder/utils.ts +0 -64
  239. package/src/decoder/wasm/asconfig.json +0 -28
  240. package/src/decoder/wasm/assembly/console.ts +0 -1
  241. package/src/decoder/wasm/assembly/index.ts +0 -890
  242. package/src/decoder/wasm/build/decoder.d.ts +0 -43
  243. package/src/decoder/wasm/build/decoder.js +0 -108
  244. package/src/decoder/wasm/build/decoder.wasm +0 -0
  245. package/src/decoder/wasm/tsconfig.json +0 -5
  246. package/src/decoder/worker.ts +0 -113
  247. package/src/go2rtc/index.ts +0 -324
  248. package/src/go2rtc/types.ts +0 -88
  249. package/src/main.ts +0 -267
  250. package/src/manager/coreManager.ts +0 -78
  251. package/src/manager/deviceManager.ts +0 -132
  252. package/src/manager/types.ts +0 -17
  253. package/src/plugins/index.ts +0 -443
  254. package/src/plugins/plugin.ts +0 -177
  255. package/src/plugins/runtime/base.ts +0 -282
  256. package/src/plugins/runtime/index.ts +0 -15
  257. package/src/plugins/runtime/node/child.ts +0 -193
  258. package/src/plugins/runtime/node/index.ts +0 -67
  259. package/src/plugins/runtime/node/plugin.ts +0 -122
  260. package/src/plugins/runtime/node/pluginApi.ts +0 -27
  261. package/src/plugins/runtime/node/proxy/cameraDevice.ts +0 -299
  262. package/src/plugins/runtime/node/proxy/coreManager.ts +0 -128
  263. package/src/plugins/runtime/node/proxy/deviceManager.ts +0 -187
  264. package/src/plugins/runtime/node/storage.ts +0 -312
  265. package/src/plugins/runtime/node/storageController.ts +0 -91
  266. package/src/plugins/runtime/python/__init__.py +0 -0
  267. package/src/plugins/runtime/python/__pycache__/__init__.cpython-311.pyc +0 -0
  268. package/src/plugins/runtime/python/__pycache__/camera_storage.cpython-311.pyc +0 -0
  269. package/src/plugins/runtime/python/__pycache__/config_service.cpython-311.pyc +0 -0
  270. package/src/plugins/runtime/python/__pycache__/constants.cpython-311.pyc +0 -0
  271. package/src/plugins/runtime/python/__pycache__/ipc.cpython-311.pyc +0 -0
  272. package/src/plugins/runtime/python/__pycache__/logger.cpython-311.pyc +0 -0
  273. package/src/plugins/runtime/python/__pycache__/message_queue.cpython-311.pyc +0 -0
  274. package/src/plugins/runtime/python/__pycache__/namespaces.cpython-311.pyc +0 -0
  275. package/src/plugins/runtime/python/__pycache__/plugin.cpython-311.pyc +0 -0
  276. package/src/plugins/runtime/python/__pycache__/plugin_api.cpython-311.pyc +0 -0
  277. package/src/plugins/runtime/python/__pycache__/plugin_logger.cpython-311.pyc +0 -0
  278. package/src/plugins/runtime/python/__pycache__/proxy_utils.cpython-311.pyc +0 -0
  279. package/src/plugins/runtime/python/__pycache__/schema.cpython-311.pyc +0 -0
  280. package/src/plugins/runtime/python/__pycache__/storage.cpython-311.pyc +0 -0
  281. package/src/plugins/runtime/python/__pycache__/storage_controller.cpython-311.pyc +0 -0
  282. package/src/plugins/runtime/python/__pycache__/typings.cpython-311.pyc +0 -0
  283. package/src/plugins/runtime/python/child.py +0 -248
  284. package/src/plugins/runtime/python/index.ts +0 -73
  285. package/src/plugins/runtime/python/namespaces.py +0 -101
  286. package/src/plugins/runtime/python/plugin.py +0 -155
  287. package/src/plugins/runtime/python/plugin_api.py +0 -29
  288. package/src/plugins/runtime/python/proxy/__pycache__/camera_device.cpython-310.pyc +0 -0
  289. package/src/plugins/runtime/python/proxy/__pycache__/camera_device.cpython-311.pyc +0 -0
  290. package/src/plugins/runtime/python/proxy/__pycache__/camera_device.cpython-38.pyc +0 -0
  291. package/src/plugins/runtime/python/proxy/__pycache__/camera_device.cpython-39.pyc +0 -0
  292. package/src/plugins/runtime/python/proxy/__pycache__/constants.cpython-311.pyc +0 -0
  293. package/src/plugins/runtime/python/proxy/__pycache__/constants.cpython-39.pyc +0 -0
  294. package/src/plugins/runtime/python/proxy/__pycache__/core_manager.cpython-311.pyc +0 -0
  295. package/src/plugins/runtime/python/proxy/__pycache__/device_manager.cpython-310.pyc +0 -0
  296. package/src/plugins/runtime/python/proxy/__pycache__/device_manager.cpython-311.pyc +0 -0
  297. package/src/plugins/runtime/python/proxy/__pycache__/device_manager.cpython-38.pyc +0 -0
  298. package/src/plugins/runtime/python/proxy/__pycache__/device_manager.cpython-39.pyc +0 -0
  299. package/src/plugins/runtime/python/proxy/__pycache__/generate_keys.cpython-310.pyc +0 -0
  300. package/src/plugins/runtime/python/proxy/__pycache__/generate_keys.cpython-311.pyc +0 -0
  301. package/src/plugins/runtime/python/proxy/__pycache__/generate_keys.cpython-38.pyc +0 -0
  302. package/src/plugins/runtime/python/proxy/__pycache__/generate_keys.cpython-39.pyc +0 -0
  303. package/src/plugins/runtime/python/proxy/__pycache__/message_queue.cpython-310.pyc +0 -0
  304. package/src/plugins/runtime/python/proxy/__pycache__/message_queue.cpython-311.pyc +0 -0
  305. package/src/plugins/runtime/python/proxy/__pycache__/message_queue.cpython-38.pyc +0 -0
  306. package/src/plugins/runtime/python/proxy/__pycache__/message_queue.cpython-39.pyc +0 -0
  307. package/src/plugins/runtime/python/proxy/__pycache__/plugins_manager.cpython-310.pyc +0 -0
  308. package/src/plugins/runtime/python/proxy/__pycache__/plugins_manager.cpython-311.pyc +0 -0
  309. package/src/plugins/runtime/python/proxy/__pycache__/plugins_manager.cpython-38.pyc +0 -0
  310. package/src/plugins/runtime/python/proxy/__pycache__/plugins_manager.cpython-39.pyc +0 -0
  311. package/src/plugins/runtime/python/proxy/__pycache__/system_manager.cpython-310.pyc +0 -0
  312. package/src/plugins/runtime/python/proxy/__pycache__/system_manager.cpython-311.pyc +0 -0
  313. package/src/plugins/runtime/python/proxy/__pycache__/system_manager.cpython-38.pyc +0 -0
  314. package/src/plugins/runtime/python/proxy/__pycache__/system_manager.cpython-39.pyc +0 -0
  315. package/src/plugins/runtime/python/proxy/camera_device.py +0 -1732
  316. package/src/plugins/runtime/python/proxy/core_manager.py +0 -126
  317. package/src/plugins/runtime/python/proxy/device_manager.py +0 -197
  318. package/src/plugins/runtime/python/schema.py +0 -99
  319. package/src/plugins/runtime/python/storage.py +0 -353
  320. package/src/plugins/runtime/python/storage_controller.py +0 -102
  321. package/src/plugins/runtime/python/typings.py +0 -195
  322. package/src/plugins/schema.ts +0 -472
  323. package/src/plugins/types.ts +0 -60
  324. package/src/plugins/worker.ts +0 -250
  325. package/src/rpc/index.ts +0 -149
  326. package/src/rpc/namespaces.ts +0 -79
  327. package/src/rpc/server.ts +0 -422
  328. package/src/rpc/types.ts +0 -119
  329. package/src/rpc/utils.ts +0 -16
  330. package/src/services/config/constants.ts +0 -47
  331. package/src/services/config/defaults.ts +0 -57
  332. package/src/services/config/index.ts +0 -744
  333. package/src/services/config/types.ts +0 -211
  334. package/src/services/logger/index.ts +0 -96
  335. package/src/types.ts +0 -47
  336. package/src/utils/path.ts +0 -16
  337. package/src/utils/pythonInstaller.ts +0 -597
  338. package/tsconfig.json +0 -37
  339. package/types/fastify.d.ts +0 -14
  340. package/updates.config.js +0 -3
  341. /package/dist/interface/assets/{@xterm.DYP7pi_n.0.0.50-internal.0.css → @xterm.DYP7pi_n.0.0.50-internal.2.css} +0 -0
  342. /package/dist/interface/assets/{Adminpanel.BKek2EMH.0.0.50-internal.0.css → Adminpanel.BKek2EMH.0.0.50-internal.2.css} +0 -0
  343. /package/dist/interface/assets/{Cameras.BDWZJqPN.0.0.50-internal.0.css → Cameras.BDWZJqPN.0.0.50-internal.2.css} +0 -0
  344. /package/dist/interface/assets/{Camview.BFUFMoNX.0.0.50-internal.0.css → Camview.BFUFMoNX.0.0.50-internal.2.css} +0 -0
  345. /package/dist/interface/assets/{CuiConsole.DCYyxdVg.0.0.50-internal.0.css → CuiConsole.DCYyxdVg.0.0.50-internal.2.css} +0 -0
  346. /package/dist/interface/assets/{CuiPluginCard.yF8V0SZY.0.0.50-internal.0.css → CuiPluginCard.yF8V0SZY.0.0.50-internal.2.css} +0 -0
  347. /package/dist/interface/assets/{CuiTimeline.BkIwlYtw.0.0.50-internal.0.css → CuiTimeline.BkIwlYtw.0.0.50-internal.2.css} +0 -0
  348. /package/dist/interface/assets/{Plugin.DJElsAn5.0.0.50-internal.0.css → Plugin.DJElsAn5.0.0.50-internal.2.css} +0 -0
  349. /package/dist/interface/assets/{Plugins.0h77qnmN.0.0.50-internal.0.css → Plugins.0h77qnmN.0.0.50-internal.2.css} +0 -0
  350. /package/dist/interface/assets/{Settings.CkgfRkQr.0.0.50-internal.0.css → Settings.CkgfRkQr.0.0.50-internal.2.css} +0 -0
  351. /package/dist/interface/assets/{SettingsAccount.DeFul3eQ.0.0.50-internal.0.css → SettingsAccount.DeFul3eQ.0.0.50-internal.2.css} +0 -0
  352. /package/dist/interface/assets/{SettingsBackup.CX0rT0QJ.0.0.50-internal.0.css → SettingsBackup.CX0rT0QJ.0.0.50-internal.2.css} +0 -0
  353. /package/dist/interface/assets/{highlight.Ch2EwETz.0.0.50-internal.0.css → highlight.Ch2EwETz.0.0.50-internal.2.css} +0 -0
  354. /package/dist/interface/assets/{logo-256.BCQk9H1-.0.0.50-internal.0.png → logo-256.BCQk9H1-.0.0.50-internal.2.png} +0 -0
  355. /package/dist/interface/assets/{logo-512.DLKVOU2S.0.0.50-internal.0.png → logo-512.DLKVOU2S.0.0.50-internal.2.png} +0 -0
  356. /package/dist/interface/assets/{logo.DmEiRk0z.0.0.50-internal.0.png → logo.DmEiRk0z.0.0.50-internal.2.png} +0 -0
  357. /package/dist/interface/assets/{main.Cip9LkS3.0.0.50-internal.0.css → main.Cip9LkS3.0.0.50-internal.2.css} +0 -0
  358. /package/dist/interface/assets/{mode-json.Br7xisR1.0.0.50-internal.0.js → mode-json.Br7xisR1.0.0.50-internal.2.js} +0 -0
  359. /package/dist/interface/assets/{mode-yaml.CIYL8U3d.0.0.50-internal.0.js → mode-yaml.CIYL8U3d.0.0.50-internal.2.js} +0 -0
  360. /package/dist/interface/assets/{worker-base.jEXLGV2h.0.0.50-internal.0.js → worker-base.jEXLGV2h.0.0.50-internal.2.js} +0 -0
  361. /package/dist/interface/assets/{worker-json.DgwNIOck.0.0.50-internal.0.js → worker-json.DgwNIOck.0.0.50-internal.2.js} +0 -0
  362. /package/dist/interface/assets/{worker-yaml.B3uUYINB.0.0.50-internal.0.js → worker-yaml.B3uUYINB.0.0.50-internal.2.js} +0 -0
  363. /package/dist/interface/js/{@babel.l0sNRNKZ.0.0.50-internal.0.js → @babel.l0sNRNKZ.0.0.50-internal.2.js} +0 -0
  364. /package/dist/interface/js/{@intlify.BkGPX90O.0.0.50-internal.0.js → @intlify.BkGPX90O.0.0.50-internal.2.js} +0 -0
  365. /package/dist/interface/js/{@kurkle.D8fDXNIl.0.0.50-internal.0.js → @kurkle.D8fDXNIl.0.0.50-internal.2.js} +0 -0
  366. /package/dist/interface/js/{@primeuix.BFAY2Bk9.0.0.50-internal.0.js → @primeuix.BFAY2Bk9.0.0.50-internal.2.js} +0 -0
  367. /package/dist/interface/js/{@react-dnd.CcwRs9xb.0.0.50-internal.0.js → @react-dnd.CcwRs9xb.0.0.50-internal.2.js} +0 -0
  368. /package/dist/interface/js/{@socket.io.Dkula2eQ.0.0.50-internal.0.js → @socket.io.Dkula2eQ.0.0.50-internal.2.js} +0 -0
  369. /package/dist/interface/js/{@vue.B5vqhCp2.0.0.50-internal.0.js → @vue.B5vqhCp2.0.0.50-internal.2.js} +0 -0
  370. /package/dist/interface/js/{@xterm.CAa7rpjv.0.0.50-internal.0.js → @xterm.C-5Lxnx_.0.0.50-internal.2.js} +0 -0
  371. /package/dist/interface/js/{axios.DHr9lByg.0.0.50-internal.0.js → axios.DHr9lByg.0.0.50-internal.2.js} +0 -0
  372. /package/dist/interface/js/{birpc.l0sNRNKZ.0.0.50-internal.0.js → birpc.l0sNRNKZ.0.0.50-internal.2.js} +0 -0
  373. /package/dist/interface/js/{compare-versions.DqEOhma6.0.0.50-internal.0.js → compare-versions.DqEOhma6.0.0.50-internal.2.js} +0 -0
  374. /package/dist/interface/js/{dijkstrajs.C00ieaqj.0.0.50-internal.0.js → dijkstrajs.C00ieaqj.0.0.50-internal.2.js} +0 -0
  375. /package/dist/interface/js/{engine.io-parser.BiEtp6m2.0.0.50-internal.0.js → engine.io-parser.BiEtp6m2.0.0.50-internal.2.js} +0 -0
  376. /package/dist/interface/js/{entities.C20TfXL6.0.0.50-internal.0.js → entities.C20TfXL6.0.0.50-internal.2.js} +0 -0
  377. /package/dist/interface/js/{ev-emitter.X5f1qa-c.0.0.50-internal.0.js → ev-emitter.X5f1qa-c.0.0.50-internal.2.js} +0 -0
  378. /package/dist/interface/js/{get-size.D1dS-IaP.0.0.50-internal.0.js → get-size.D1dS-IaP.0.0.50-internal.2.js} +0 -0
  379. /package/dist/interface/js/{hookable.l0sNRNKZ.0.0.50-internal.0.js → hookable.l0sNRNKZ.0.0.50-internal.2.js} +0 -0
  380. /package/dist/interface/js/{mdurl.k9Sl0PQj.0.0.50-internal.0.js → mdurl.k9Sl0PQj.0.0.50-internal.2.js} +0 -0
  381. /package/dist/interface/js/{perfect-debounce.l0sNRNKZ.0.0.50-internal.0.js → perfect-debounce.l0sNRNKZ.0.0.50-internal.2.js} +0 -0
  382. /package/dist/interface/js/{primelocale.Bga3dOQu.0.0.50-internal.0.js → primelocale.Bga3dOQu.0.0.50-internal.2.js} +0 -0
  383. /package/dist/interface/js/{punycode.js.Dj65hjkv.0.0.50-internal.0.js → punycode.js.Dj65hjkv.0.0.50-internal.2.js} +0 -0
  384. /package/dist/interface/js/{react-dnd-html5-backend.1HQjlkwI.0.0.50-internal.0.js → react-dnd-html5-backend.1HQjlkwI.0.0.50-internal.2.js} +0 -0
  385. /package/dist/interface/js/{redux.BFxtlG_c.0.0.50-internal.0.js → redux.BFxtlG_c.0.0.50-internal.2.js} +0 -0
  386. /package/dist/interface/js/{tslib.9k7AwCpt.0.0.50-internal.0.js → tslib.9k7AwCpt.0.0.50-internal.2.js} +0 -0
  387. /package/dist/interface/js/{uc.micro.kMc2yuuw.0.0.50-internal.0.js → uc.micro.kMc2yuuw.0.0.50-internal.2.js} +0 -0
  388. /package/dist/interface/js/{uuid.C6aID195.0.0.50-internal.0.js → uuid.C6aID195.0.0.50-internal.2.js} +0 -0
  389. /package/dist/interface/js/{vue.l0sNRNKZ.0.0.50-internal.0.js → vue.l0sNRNKZ.0.0.50-internal.2.js} +0 -0
  390. /package/dist/interface/js/{zod.SKKegNRO.0.0.50-internal.0.js → zod.SKKegNRO.0.0.50-internal.2.js} +0 -0
@@ -1,883 +0,0 @@
1
- process.title = process.argv[2] ?? 'camera.ui - Frame Worker';
2
-
3
- import { Logger, SignalHandler, sleep } from '@camera.ui/common';
4
- import { ClientInstance } from '@camera.ui/rpc-client';
5
- import { rpc } from '@camera.ui/rpc-common';
6
- import { spawn } from 'node:child_process';
7
- import { fileURLToPath } from 'node:url';
8
-
9
- import { NamespaceManager } from '../rpc/namespaces.js';
10
- import { ImageUtils } from './imageUtils.js';
11
- import { createSingleConnectionServer } from './utils.js';
12
-
13
- import type { LoggerOptions } from '@camera.ui/common';
14
- import type { Promisify } from '@camera.ui/rpc-common';
15
- import type {
16
- CameraFrameWorkerDecoder,
17
- CameraFrameWorkerResolution,
18
- CoreManager as CoreManagerInterface,
19
- DecoderFormat,
20
- FfmpegArgs,
21
- FrameBuffer,
22
- FrameData,
23
- FrameMetadata,
24
- ImageInformation,
25
- ImageOptions,
26
- } from '@camera.ui/types';
27
- import type { ChildProcess } from 'node:child_process';
28
- import type { Socket } from 'node:net';
29
- import type { CoreManagerNamespaces, FrameWorkerNamespaces } from '../rpc/namespaces.js';
30
- import type { BaseFrameWorkerConfig, FrameWorkerInterface, PixelFormat, WorkerToMainMessage } from './types.js';
31
- import type { TCPConnectionDetails } from './utils.js';
32
-
33
- const PIXEL_FORMAT: PixelFormat = 'yuv420p';
34
- const METADATA_REGEX = /s:\s*(\d+x\d+)/;
35
-
36
- interface Frame {
37
- data: Buffer;
38
- timestamp: number;
39
- metadata: FrameMetadata;
40
- }
41
-
42
- class FFmpegStream {
43
- private readonly frameSize: number;
44
- private readonly width: number;
45
- private readonly height: number;
46
-
47
- // Process Management
48
- private ffmpegProcess?: ChildProcess;
49
- private activeViewers = 0;
50
- private ffmpegHwOptions?: FfmpegArgs;
51
- private server?: TCPConnectionDetails;
52
- public socket?: Socket;
53
-
54
- // State
55
- public streamActive = false;
56
- public metadata?: FrameMetadata;
57
- private isShuttingDown = false;
58
- private streamStartTimeout = 60000;
59
- private initializationPromise: Promise<void> | null = null;
60
-
61
- // Reconnection Logic
62
- private reconnectCount = 0;
63
-
64
- // Frame Queue Management
65
- private frameBuffer: Frame[] = [];
66
- private lastFrame: Frame | null = null;
67
- private queueConsumers = new Set<FrameConsumer>();
68
- private frameProcessingActive = false;
69
- private bufferDurationMs = 5000;
70
-
71
- // Health Check
72
- private healthCheckInterval?: NodeJS.Timeout;
73
- private lastFrameTimestamp = 0;
74
- private healthCheckTime = 5000;
75
- private maxFrameTime = 15000;
76
-
77
- // Consumer management
78
- private nextConsumerId = 0;
79
-
80
- private get bytesPerPixel(): number {
81
- switch (this.pixelFormat) {
82
- case 'yuv420p':
83
- case 'nv12':
84
- return 1.5;
85
- case 'rgb24':
86
- return 3;
87
- }
88
- }
89
-
90
- private get pixelFormat(): PixelFormat {
91
- if (this.worker.imageUtils.decoder === 'gpu') {
92
- return 'nv12';
93
- } else {
94
- return PIXEL_FORMAT;
95
- }
96
- }
97
-
98
- constructor(private worker: FrameWorkerChild) {
99
- const [width, height] = worker.config.resolution.split('x').map(Number);
100
- this.width = width;
101
- this.height = height;
102
- this.frameSize = width * height * this.bytesPerPixel;
103
- }
104
-
105
- public async initialize(): Promise<void> {
106
- if (this.initializationPromise) {
107
- return this.initializationPromise;
108
- }
109
-
110
- if (this.streamActive) {
111
- return;
112
- }
113
-
114
- try {
115
- this.initializationPromise = this.startStreamProcess();
116
- await this.initializationPromise;
117
- } finally {
118
- this.initializationPromise = null;
119
- }
120
- }
121
-
122
- public close(): void {
123
- if (!this.streamActive) {
124
- return;
125
- }
126
-
127
- this.worker.logger.trace('Closing FFmpeg stream');
128
- this.cleanupResources();
129
- }
130
-
131
- public cleanup(): void {
132
- this.isShuttingDown = true;
133
- this.cleanupResources();
134
- }
135
-
136
- public registerViewer(): FrameConsumer {
137
- this.activeViewers++;
138
- const consumer = new FrameConsumer(this.nextConsumerId++, this);
139
- this.queueConsumers.add(consumer);
140
- return consumer;
141
- }
142
-
143
- public unregisterViewer(consumer: FrameConsumer): void {
144
- this.queueConsumers.delete(consumer);
145
- this.activeViewers--;
146
- if (this.activeViewers <= 0) {
147
- this.activeViewers = 0;
148
- this.close();
149
- }
150
- }
151
-
152
- public getNextFrame(timestamp: number): Frame | null {
153
- if (!this.lastFrame) {
154
- return null;
155
- }
156
-
157
- if (this.lastFrame.timestamp <= timestamp) {
158
- return null;
159
- }
160
-
161
- return {
162
- data: Buffer.from(this.lastFrame.data),
163
- timestamp: this.lastFrame.timestamp,
164
- metadata: this.lastFrame.metadata,
165
- };
166
- }
167
-
168
- public getFrameByTimestamp(timestamp: number, maxDifference = 0): Frame | undefined {
169
- if (this.frameBuffer.length === 0) {
170
- return undefined;
171
- }
172
-
173
- // Quick boundary checks
174
- const firstFrame = this.frameBuffer[0];
175
- const lastFrame = this.frameBuffer[this.frameBuffer.length - 1];
176
-
177
- // Check if timestamp is outside our buffer range (plus maxDifference)
178
- if (timestamp < firstFrame.timestamp - maxDifference || timestamp > lastFrame.timestamp + maxDifference) {
179
- return undefined;
180
- }
181
-
182
- // Binary search for closest frame
183
- let left = 0;
184
- let right = this.frameBuffer.length - 1;
185
-
186
- while (left <= right) {
187
- const mid = Math.floor((left + right) / 2);
188
- const frame = this.frameBuffer[mid];
189
- const diff = frame.timestamp - timestamp;
190
-
191
- // Exact match
192
- if (diff === 0) {
193
- return frame;
194
- }
195
-
196
- if (diff < 0) {
197
- left = mid + 1;
198
- } else {
199
- right = mid - 1;
200
- }
201
- }
202
-
203
- // If we need exact match only
204
- if (maxDifference === 0) {
205
- return undefined;
206
- }
207
-
208
- // Find closest frame within maxDifference
209
- // After binary search, 'left' points to the insertion point
210
- // Check frames around this point
211
- const candidates = [this.frameBuffer[Math.max(0, left - 1)], this.frameBuffer[Math.min(this.frameBuffer.length - 1, left)]];
212
-
213
- let bestMatch: Frame | undefined;
214
- let smallestDiff = Infinity;
215
-
216
- for (const frame of candidates) {
217
- const diff = Math.abs(frame.timestamp - timestamp);
218
- if (diff <= maxDifference && diff < smallestDiff) {
219
- smallestDiff = diff;
220
- bestMatch = frame;
221
- }
222
- }
223
-
224
- if (bestMatch) {
225
- return bestMatch;
226
- }
227
-
228
- return undefined;
229
- }
230
-
231
- private async startStreamProcess(): Promise<void> {
232
- try {
233
- await this.launchStream();
234
- this.reconnectCount = 0;
235
- } catch (error) {
236
- if (this.isShuttingDown || this.activeViewers === 0) {
237
- return;
238
- }
239
-
240
- this.reconnectCount = this.reconnectCount < 10 ? this.reconnectCount + 1 : 10;
241
- const delay = this.calculateReconnectDelay();
242
- this.worker.logger.warn(`Connection failed, retrying in ${delay / 1000}s`);
243
- this.worker.logger.debug('Error:', error.message);
244
-
245
- await sleep(delay);
246
- this.worker.logger.debug('Retrying connection...');
247
- return this.startStreamProcess();
248
- }
249
- }
250
-
251
- private async launchStream(): Promise<void> {
252
- if (this.activeViewers === 0) {
253
- this.worker.logger.debug('No active consumers, not starting stream');
254
- return;
255
- }
256
-
257
- this.cleanupResources();
258
-
259
- this.server = await createSingleConnectionServer('127.0.0.1', {
260
- noDelay: true,
261
- // keepAlive: true,
262
- highWaterMark: this.frameSize * 10,
263
- });
264
-
265
- const ffmpegArguments = await this.prepareFfmpegArguments(this.server.serverUrl);
266
- this.worker.logger.trace('Starting FFmpeg with args:', this.worker.config.ffmpegPath, ffmpegArguments.join(' '));
267
-
268
- this.ffmpegProcess = spawn(this.worker.config.ffmpegPath, ffmpegArguments, {
269
- stdio: ['ignore', 'ignore', 'pipe'],
270
- });
271
-
272
- this.ffmpegProcess.once('exit', async () => {
273
- if (this.activeViewers > 0 && !this.isShuttingDown) {
274
- this.cleanupResources();
275
- this.worker.logger.warn('FFmpeg process exited unexpectedly, restarting in 10 seconds...');
276
- await sleep(10000);
277
- this.initialize();
278
- } else {
279
- this.worker.logger.debug('FFmpeg process exited');
280
- }
281
- });
282
-
283
- try {
284
- this.socket = await this.server.connectionPromise;
285
- this.metadata = await this.extractMetadata();
286
- this.ffmpegProcess.stderr?.destroy();
287
- this.streamActive = true;
288
- this.startFrameProcessing();
289
- this.startHealthCheck();
290
- } catch (error) {
291
- this.cleanupResources();
292
- throw error;
293
- }
294
- }
295
-
296
- private startHealthCheck(): void {
297
- clearInterval(this.healthCheckInterval);
298
- this.healthCheckInterval = setInterval(() => {
299
- if (!this.streamActive || this.activeViewers === 0) {
300
- return;
301
- }
302
-
303
- const now = Date.now();
304
- const timeSinceLastFrame = now - this.lastFrameTimestamp;
305
-
306
- // If no frames for 30 seconds and we have active viewers, restart
307
- if (this.lastFrameTimestamp > 0 && timeSinceLastFrame > this.maxFrameTime && this.activeViewers > 0) {
308
- this.worker.logger.warn(`No frames received in ${timeSinceLastFrame / 1000}s! This may be due to a network issue, FFmpeg failure or high load on the system.`);
309
- this.worker.logger.log('Restarting...');
310
- this.cleanupResources();
311
- this.initialize();
312
- }
313
- }, this.healthCheckTime);
314
- }
315
-
316
- private async startFrameProcessing(): Promise<void> {
317
- if (this.frameProcessingActive || !this.socket || !this.metadata) {
318
- return;
319
- }
320
-
321
- let firstChunkReceived = false;
322
- let firstFrameReceived = false;
323
- this.frameProcessingActive = true;
324
- const metadata = this.metadata;
325
- let buffer = Buffer.alloc(0);
326
- let lastBufferSize = 0;
327
-
328
- try {
329
- for await (const chunk of this.socket as AsyncIterable<Buffer>) {
330
- if (!this.frameProcessingActive) {
331
- break;
332
- }
333
-
334
- if (!chunk.length) {
335
- this.worker.logger.warn('Received empty chunk from FFmpeg');
336
- continue;
337
- }
338
-
339
- if (buffer.length > metadata.frameSize * 10) {
340
- this.worker.logger.warn(`Buffer growing: ${buffer.length} bytes (${(buffer.length / metadata.frameSize).toFixed(2)} frames)`);
341
- }
342
-
343
- if (!firstChunkReceived) {
344
- this.worker.logger.trace('First chunk received');
345
- firstChunkReceived = true;
346
- }
347
-
348
- buffer = Buffer.concat([buffer, chunk]);
349
-
350
- while (buffer.length >= metadata.frameSize) {
351
- const frameData = buffer.subarray(0, metadata.frameSize);
352
- buffer = buffer.subarray(metadata.frameSize);
353
-
354
- if (lastBufferSize === buffer.length && buffer.length > 0) {
355
- this.worker.logger.warn(`Possible issue: Buffer size not changing: ${buffer.length} bytes`);
356
- // buffer = Buffer.alloc(0);
357
- break;
358
- }
359
-
360
- lastBufferSize = buffer.length;
361
-
362
- if (!firstFrameReceived) {
363
- this.worker.logger.trace('First frame received');
364
- firstFrameReceived = true;
365
- }
366
-
367
- this.addFrameToQueue(frameData, this.metadata);
368
- }
369
- }
370
- } catch (error) {
371
- this.worker.logger.error('Error in frame processing:', error);
372
- } finally {
373
- this.frameProcessingActive = false;
374
- }
375
- }
376
-
377
- private addFrameToQueue(frameData: Buffer, metadata: FrameMetadata): void {
378
- const timestamp = Date.now();
379
- this.lastFrameTimestamp = timestamp;
380
-
381
- const newFrame: Frame = {
382
- data: frameData,
383
- timestamp,
384
- metadata,
385
- };
386
-
387
- this.frameBuffer.push(newFrame);
388
- this.lastFrame = newFrame;
389
- this.cleanupOldFrames();
390
-
391
- // Notify all consumers that a new frame is available
392
- for (const consumer of this.queueConsumers) {
393
- consumer.notifyNewFrame();
394
- }
395
- }
396
-
397
- private cleanupOldFrames(): void {
398
- const currentTime = Date.now();
399
- const bufferThreshold = currentTime - this.bufferDurationMs;
400
-
401
- while (this.frameBuffer.length > 1 && this.frameBuffer[0].timestamp < bufferThreshold) {
402
- this.frameBuffer.shift();
403
- }
404
- }
405
-
406
- private async extractMetadata(): Promise<FrameMetadata> {
407
- return new Promise((resolve, reject) => {
408
- const timeout = setTimeout(() => {
409
- cleanup();
410
- reject(new Error('FFmpeg stream start timeout'));
411
- }, this.streamStartTimeout);
412
-
413
- const onData = (data: Buffer) => {
414
- const metadata = this.parseMetadataFromStderr(data);
415
- if (metadata) {
416
- this.worker.logger.debug('Metadata received:', metadata);
417
- cleanup();
418
- resolve(metadata);
419
- }
420
- };
421
-
422
- const cleanup = () => {
423
- clearTimeout(timeout);
424
- this.ffmpegProcess?.stderr?.removeListener('data', onData);
425
- };
426
-
427
- this.ffmpegProcess?.stderr?.on('data', onData);
428
- });
429
- }
430
-
431
- private calculateReconnectDelay(): number {
432
- if (this.reconnectCount === 10) {
433
- return 60000;
434
- } else {
435
- return 10000;
436
- }
437
- }
438
-
439
- private parseMetadataFromStderr(data: Buffer): FrameMetadata | undefined {
440
- const stderrText = data.toString();
441
- if (!stderrText) {
442
- return;
443
- }
444
-
445
- const match = METADATA_REGEX.exec(stderrText);
446
- if (!match?.[1]) {
447
- return;
448
- }
449
-
450
- const [originalWidth, originalHeight] = match[1].split('x').map((v) => parseInt(v, 10));
451
- const frameDataSize = this.width * this.height * this.bytesPerPixel;
452
-
453
- const metadata: FrameMetadata = {
454
- format: this.worker.imageUtils.decoder === 'gpu' ? 'nv12' : 'yuv420p',
455
- frameSize: frameDataSize,
456
- width: this.width,
457
- height: this.height,
458
- origHeight: originalHeight,
459
- origWidth: originalWidth,
460
- };
461
-
462
- return metadata;
463
- }
464
-
465
- private async prepareFfmpegArguments(serverUrl: string): Promise<string[]> {
466
- if (!this.ffmpegHwOptions) {
467
- const coreManager = await this.coreManagerProxy();
468
- this.ffmpegHwOptions = (
469
- await coreManager.getHwaccelInfo({
470
- targetCodec: 'h264',
471
- keepOnHardware: true,
472
- pixelFormat: this.pixelFormat,
473
- scale: {
474
- width: this.width,
475
- height: this.height,
476
- },
477
- })
478
- )[0];
479
- }
480
-
481
- const filterChain: string[] = ['showinfo=checksum=0', ...this.ffmpegHwOptions.hwaccelFilters];
482
- if (this.worker.config.fps > 0) {
483
- filterChain.push(`fps=fps=${this.worker.config.fps}`);
484
- }
485
-
486
- return [
487
- '-hide_banner',
488
- ...this.ffmpegHwOptions.hwaccelArgs,
489
- '-fflags',
490
- '+discardcorrupt+flush_packets+nobuffer',
491
- '-flags',
492
- 'low_delay',
493
- '-analyzeduration',
494
- '0',
495
- '-probesize',
496
- '500000',
497
- '-reorder_queue_size',
498
- '0',
499
- '-user_agent',
500
- 'camera.ui/frameworker',
501
- '-timeout',
502
- '5000000',
503
- '-rtsp_transport',
504
- 'tcp',
505
- '-re',
506
- '-i',
507
- this.worker.config.cameraSource,
508
- ...this.ffmpegHwOptions.hwDeviceArgs,
509
- '-fps_mode',
510
- 'cfr',
511
- '-vf',
512
- filterChain.join(','),
513
- '-an',
514
- '-dn',
515
- '-sn',
516
- '-f',
517
- 'rawvideo',
518
- `${serverUrl}?tcp_nodelay=1`,
519
- ];
520
- }
521
-
522
- private cleanupResources(): void {
523
- this.streamActive = false;
524
- this.metadata = undefined;
525
- this.frameProcessingActive = false;
526
-
527
- clearInterval(this.healthCheckInterval);
528
- this.healthCheckInterval = undefined;
529
-
530
- this.server?.terminate();
531
- this.server = undefined;
532
-
533
- this.ffmpegProcess?.stderr?.removeAllListeners();
534
- this.ffmpegProcess?.stderr?.destroy();
535
- this.ffmpegProcess?.removeAllListeners();
536
- this.ffmpegProcess?.kill('SIGKILL');
537
- this.ffmpegProcess = undefined;
538
- }
539
-
540
- private async coreManagerProxy(): Promise<Promisify<CoreManagerInterface>> {
541
- return await this.worker.createRPCProxy<CoreManagerInterface>(this.worker.namespaces.coreManagerRpc);
542
- }
543
- }
544
-
545
- class FrameConsumer {
546
- private lastFrameTimestamp = 0;
547
- private resolveNewFrame: (() => void) | null = null;
548
-
549
- constructor(
550
- public readonly id: number,
551
- private stream: FFmpegStream,
552
- ) {}
553
-
554
- public notifyNewFrame(): void {
555
- if (this.resolveNewFrame) {
556
- const resolve = this.resolveNewFrame;
557
- this.resolveNewFrame = null;
558
- resolve();
559
- }
560
- }
561
-
562
- public waitForNewFrame(): Promise<void> {
563
- return new Promise<void>((resolve) => {
564
- this.resolveNewFrame = resolve;
565
- });
566
- }
567
-
568
- public [Symbol.asyncIterator](): AsyncIterator<Frame> {
569
- return {
570
- next: async (): Promise<IteratorResult<Frame>> => {
571
- while (true) {
572
- const frame = this.stream.getNextFrame(this.lastFrameTimestamp);
573
-
574
- if (frame) {
575
- this.lastFrameTimestamp = frame.timestamp;
576
- return { value: frame, done: false };
577
- }
578
-
579
- if (!this.stream.streamActive) {
580
- return { value: undefined as any, done: true };
581
- }
582
-
583
- // Wait for notification of new frame
584
- await this.waitForNewFrame();
585
- }
586
- },
587
- };
588
- }
589
- }
590
-
591
- class FrameWorkerChild extends ClientInstance implements FrameWorkerInterface {
592
- public readonly config: BaseFrameWorkerConfig;
593
- public readonly namespaces: FrameWorkerNamespaces & CoreManagerNamespaces;
594
- public readonly logger: Logger;
595
- public readonly imageUtils: ImageUtils;
596
-
597
- private signalHandler: SignalHandler;
598
- private ffmpegStream: FFmpegStream;
599
-
600
- private stopped = false;
601
-
602
- constructor() {
603
- super('service', {
604
- endpoints: process.env.PROXY_ENDPOINTS!.split(','),
605
- auth: {
606
- user: process.env.PROXY_USER!,
607
- password: process.env.PROXY_PASSWORD!,
608
- },
609
- tls: {
610
- cert: process.env.PROXY_CERT!,
611
- key: process.env.PROXY_KEY!,
612
- ca: process.env.PROXY_CA!,
613
- },
614
- metadata: {
615
- id: NamespaceManager.frameWorkerNamespaces(process.env.CAMERA_ID!).frameWorkerChild,
616
- name: 'Frame Worker',
617
- },
618
- connect: {
619
- waitForServer: true,
620
- },
621
- reconnect: {
622
- enabled: true,
623
- },
624
- bundledConnection: false,
625
- });
626
-
627
- this.namespaces = {
628
- ...NamespaceManager.frameWorkerNamespaces(process.env.CAMERA_ID!),
629
- ...NamespaceManager.coreManagerNamespaces(),
630
- };
631
-
632
- this.config = {
633
- cameraId: process.env.CAMERA_ID!,
634
- cameraName: process.env.CAMERA_NAME!,
635
- cameraSource: process.env.CAMERA_SOURCE!,
636
- ffmpegPath: process.env.FFMPEG_PATH!,
637
- auth: { user: process.env.PROXY_USER!, password: process.env.PROXY_PASSWORD! },
638
- proxyEndpoints: process.env.PROXY_ENDPOINTS!.split(','),
639
- fps: parseInt(process.env.FPS!),
640
- resolution: process.env.RESOLUTION! as CameraFrameWorkerResolution,
641
- decoder: process.env.DECODER! as CameraFrameWorkerDecoder,
642
- };
643
-
644
- delete process.env.PROXY_USER;
645
- delete process.env.PROXY_PASSWORD;
646
- delete process.env.PROXY_ENDPOINTS;
647
- delete process.env.PROXY_CERT;
648
- delete process.env.PROXY_KEY;
649
- delete process.env.PROXY_CA;
650
-
651
- const loggerOptions: LoggerOptions = {
652
- prefix: 'Frame Worker',
653
- suffix: this.config.cameraName,
654
- disableTimestamps: process.env.LOGGER_DISABLE_TIMESTAMPS === '1',
655
- debugEnabled: process.env.LOGGER_LEVEL === 'debug' || process.env.LOGGER_LEVEL === 'trace',
656
- traceEnabled: process.env.LOGGER_LEVEL === 'trace',
657
- };
658
-
659
- this.logger = new Logger(loggerOptions);
660
- this.imageUtils = new ImageUtils(this.config.decoder, this.logger);
661
- this.ffmpegStream = new FFmpegStream(this);
662
- this.signalHandler = new SignalHandler({
663
- displayName: '[Signal]',
664
- timeoutDuration: 1000,
665
- logger: this.logger,
666
- closeFunction: this.close.bind(this),
667
- });
668
-
669
- this.start();
670
- }
671
-
672
- protected async onStart(): Promise<void> {
673
- await this.imageUtils.initiate();
674
- await this.registerRPCHandler(this.namespaces.frameWorkerChildRpc, this);
675
- this.sendMessage({ message: 'started', data: {} });
676
- }
677
-
678
- protected onBeforeStop(): Promise<void> {
679
- return this.close();
680
- }
681
-
682
- protected async onStop(): Promise<void> {}
683
-
684
- @rpc({ public: true })
685
- public async *generateFrames(options?: ImageOptions): AsyncGenerator<FrameData> {
686
- let consumer: FrameConsumer | undefined;
687
-
688
- try {
689
- consumer = this.ffmpegStream.registerViewer();
690
- await this.ffmpegStream.initialize();
691
-
692
- if (!this.ffmpegStream.metadata) {
693
- throw new Error('Stream metadata not available');
694
- }
695
-
696
- const metadata = this.ffmpegStream.metadata;
697
-
698
- // Use the async iterator from the consumer to get frames
699
- for await (const { data: frameData, timestamp } of consumer) {
700
- options = this.validateOptions(metadata, options);
701
-
702
- if (options) {
703
- const processedFrame = await this.processFrame(frameData, metadata.width, metadata.height, metadata.format, options);
704
- yield {
705
- data: processedFrame.image,
706
- metadata,
707
- timestamp,
708
- info: processedFrame.info,
709
- };
710
- } else {
711
- const info = this.getImageInformation(metadata.width, metadata.height, metadata.format);
712
- yield {
713
- data: frameData,
714
- metadata,
715
- timestamp,
716
- info,
717
- };
718
- }
719
- }
720
- } catch (error) {
721
- this.logger.error('Error in frame generation:', error);
722
- } finally {
723
- if (consumer) {
724
- this.ffmpegStream.unregisterViewer(consumer);
725
- }
726
- }
727
- }
728
-
729
- @rpc({ public: true })
730
- public async getPrebufferedFrame(timestamp: number, options?: ImageOptions, maxDifference = 500): Promise<FrameData | undefined> {
731
- const prebufferedFrame = this.ffmpegStream.getFrameByTimestamp(timestamp, maxDifference);
732
- if (!prebufferedFrame) {
733
- this.logger.debug(`No prebuffered frame found for timestamp ${timestamp}`);
734
- return;
735
- }
736
-
737
- const validatedOptions = options && this.validateOptions(prebufferedFrame.metadata, options);
738
-
739
- if (validatedOptions) {
740
- const processedFrame = await this.processFrame(
741
- prebufferedFrame.data,
742
- prebufferedFrame.metadata.width,
743
- prebufferedFrame.metadata.height,
744
- prebufferedFrame.metadata.format,
745
- validatedOptions,
746
- );
747
- return { data: processedFrame.image, metadata: prebufferedFrame.metadata, timestamp: prebufferedFrame.timestamp, info: processedFrame.info };
748
- } else {
749
- const info = this.getImageInformation(prebufferedFrame.metadata.width, prebufferedFrame.metadata.height, prebufferedFrame.metadata.format);
750
- return { data: prebufferedFrame.data, metadata: prebufferedFrame.metadata, timestamp: prebufferedFrame.timestamp, info };
751
- }
752
- }
753
-
754
- @rpc({ public: true })
755
- public async processFrame(
756
- frame: Buffer | Uint8Array,
757
- width: number,
758
- height: number,
759
- format: DecoderFormat | 'rgba' | 'gray',
760
- options: ImageOptions,
761
- ): Promise<FrameBuffer> {
762
- const newFrame = Buffer.isBuffer(frame) ? new Uint8Array(frame, frame.byteOffset, frame.byteLength) : frame;
763
- const info = this.getImageInformation(width, height, format, options);
764
-
765
- const image = await this.imageUtils.processImage(newFrame, width, height, format, options);
766
-
767
- return {
768
- image,
769
- info,
770
- };
771
- }
772
-
773
- private validateOptions(metadata: FrameMetadata, options: ImageOptions = {}): ImageOptions | undefined {
774
- const validated: ImageOptions = {};
775
-
776
- // Format conversion
777
- const metadataFormat = metadata.format === 'rgb24' ? 'rgb' : metadata.format;
778
- if (options.format?.to && options.format.to !== metadataFormat) {
779
- validated.format = options.format;
780
- }
781
-
782
- // Cropping
783
- if (options.crop) {
784
- const left = options.crop.left || 0;
785
- const top = options.crop.top || 0;
786
-
787
- // Validate crop parameters
788
- if (left >= metadata.width || top >= metadata.height) {
789
- return undefined;
790
- }
791
-
792
- const width = Math.min(options.crop.width ?? metadata.width, metadata.width - left);
793
- const height = Math.min(options.crop.height ?? metadata.height, metadata.height - top);
794
-
795
- if (width <= 0 || height <= 0) {
796
- return undefined;
797
- }
798
-
799
- // Skip full frame "crops"
800
- if (left === 0 && top === 0 && width === metadata.width && height === metadata.height) {
801
- // No need to include this crop as it's the full frame
802
- } else {
803
- validated.crop = {
804
- left,
805
- top,
806
- width,
807
- height,
808
- };
809
- }
810
- }
811
-
812
- // Resizing
813
- if (options.resize) {
814
- let targetWidth = options.resize.width;
815
- let targetHeight = options.resize.height;
816
-
817
- // Handle negative values (which mean "use original")
818
- if (targetWidth < 0) targetWidth = metadata.width;
819
- if (targetHeight < 0) targetHeight = metadata.height;
820
-
821
- // Calculate missing dimension if only one is provided
822
- if (targetWidth > 0 && targetHeight === 0) {
823
- targetHeight = Math.round((targetWidth * metadata.height) / metadata.width);
824
- } else if (targetHeight > 0 && targetWidth === 0) {
825
- targetWidth = Math.round((targetHeight * metadata.width) / metadata.height);
826
- }
827
-
828
- // Skip if no resize needed
829
- if ((targetWidth === 0 && targetHeight === 0) || (targetWidth === metadata.width && targetHeight === metadata.height)) {
830
- // Skip as it's the same as original
831
- } else {
832
- validated.resize = {
833
- width: targetWidth,
834
- height: targetHeight,
835
- };
836
- }
837
- }
838
-
839
- // Return undefined if no transformations are needed
840
- return Object.keys(validated).length > 0 ? validated : undefined;
841
- }
842
-
843
- private getImageInformation(inputWidth: number, inputHeight: number, inputFormat: DecoderFormat | 'rgba' | 'gray', options?: ImageOptions): ImageInformation {
844
- // Calculate output width
845
- const width = options?.resize?.width ?? (options?.crop ? Math.min(options.crop.width + (options.crop.left || 0), inputWidth - (options.crop.left || 0)) : inputWidth);
846
-
847
- // Calculate output height
848
- const height =
849
- options?.resize?.height ?? (options?.crop ? Math.min(options.crop.height + (options.crop.top || 0), inputHeight - (options.crop.top || 0)) : inputHeight);
850
-
851
- // Determine output format
852
- let format = options?.format?.to ?? inputFormat;
853
- format = format === 'rgb24' ? 'rgb' : format;
854
-
855
- // Calculate channels based on format
856
- const channels = format === 'rgba' ? 4 : format === 'rgb' ? 3 : format === 'gray' ? 1 : 1.5;
857
-
858
- return {
859
- width,
860
- height,
861
- channels,
862
- format,
863
- };
864
- }
865
-
866
- private sendMessage(message: WorkerToMainMessage): void {
867
- this.sendToServer<WorkerToMainMessage>(message);
868
- }
869
-
870
- private async close(): Promise<void> {
871
- if (this.stopped) {
872
- return;
873
- }
874
-
875
- this.stopped = true;
876
- this.ffmpegStream.cleanup();
877
- await this.stop();
878
- }
879
- }
880
-
881
- if (process.argv[1] === fileURLToPath(import.meta.url)) {
882
- new FrameWorkerChild();
883
- }