Compare commits

..

651 Commits

Author SHA1 Message Date
Koushik Dutta
207f00733e lxc-docker: abort on any container exit. potentially bad with watchtower updates. 2024-10-17 09:32:03 -07:00
Koushik Dutta
bc4b2c956c postbeta 2024-10-17 09:23:34 -07:00
Koushik Dutta
e15578c9ca proxmox: intel microcode 2024-10-16 20:38:12 -07:00
Koushik Dutta
e2c5ee2400 proxmox: intel microcode 2024-10-16 20:38:04 -07:00
Koushik Dutta
dec62ddbc6 proxmox: intel microcode 2024-10-16 20:37:24 -07:00
Koushik Dutta
e7a65c4a28 Merge branch 'main' of github.com:koush/scrypted 2024-10-16 13:32:58 -07:00
Koushik Dutta
127855c57e core: bump lxc intel icd 2024-10-16 13:32:53 -07:00
Koushik Dutta
d9f35ef461 proxmox: broader udev rules 2024-10-16 10:52:00 -07:00
Koushik Dutta
787c452105 sdk: improve deeplinks 2024-10-15 09:56:19 -07:00
Koushik Dutta
3556b326f5 core: update 2024-10-15 09:42:05 -07:00
Koushik Dutta
dd42878a5f Merge branch 'main' of github.com:koush/scrypted 2024-10-15 09:41:26 -07:00
Koushik Dutta
07db378763 sdk: deeplink support 2024-10-14 18:17:55 -07:00
Koushik Dutta
df142635b8 postbeta 2024-10-11 18:32:42 -07:00
Brett Jia
24bcc32532 server: aggressively catch child process pipe errors (#1609)
* server: aggressively catch python child process pipe errors

* document error behavior

* move stdio error handling to setupWorker

* handle undefined stdio
2024-10-11 15:34:44 -07:00
Koushik Dutta
5856ad60dd webrtc: fix opus crash 2024-10-10 10:48:40 -07:00
Koushik Dutta
124da3c1b7 webrtc: max compat mode should reset 2024-10-10 10:36:53 -07:00
Koushik Dutta
005efbfe82 webrtc: add flag that forces opus audio 2024-10-10 10:27:07 -07:00
Koushik Dutta
cb955f403d lxc-docker: remove nvidia container toolkit 2024-10-09 22:43:17 -07:00
Koushik Dutta
fa38d8c560 lxc-docker: ensure a unique WATCHTOWER_HTTP_API_TOKEN is used every launch 2024-10-09 17:56:37 -07:00
Koushik Dutta
0e4a94cd6e install: SCRYPTED_LXC env automatically installs more stuff 2024-10-09 17:44:54 -07:00
Koushik Dutta
a0c3721140 docker: move container toolkit script 2024-10-09 17:43:48 -07:00
Koushik Dutta
7efffe4c51 docker: default values in case env file goes missing 2024-10-09 17:28:01 -07:00
Koushik Dutta
2ff80780f8 install: fix watchtower arg 2024-10-09 16:37:26 -07:00
Koushik Dutta
9a41e3bc29 lxc-docker: force container recreate and move watchtower auto update into modifiable env. 2024-10-09 16:29:36 -07:00
Koushik Dutta
23de4011fb lxc-docker: reenable watchtower 2024-10-09 16:08:57 -07:00
Koushik Dutta
4fba5b9484 install: generate watchtower token at install time via env 2024-10-09 15:28:41 -07:00
Koushik Dutta
0dcfa367a6 Merge branch 'main' of github.com:koush/scrypted 2024-10-09 15:15:56 -07:00
Koushik Dutta
8e63943f53 install: generate watchtower token at install time via env 2024-10-09 15:15:52 -07:00
apocaliss92
e2d78611c5 reolink: preset supports
* Reolink presets supported

* Round changed with ceil to avoid sending 0

* ptzOp detached to a specific one

* Preset command moved as first

* Return added

* Unecessary ptz condition removed

---------

Co-authored-by: Gianluca Ruocco <gianluca.ruocco@xarvio.com>
2024-10-09 14:04:21 -07:00
Koushik Dutta
8a94c268ac nvidia: simplify with new docker image 2024-10-09 13:29:53 -07:00
Koushik Dutta
10bdef414e install: auto enable nvidia gpus and capabilities 2024-10-09 13:06:54 -07:00
Koushik Dutta
317ee80477 install: nvidia container toolkit fixes 2024-10-09 12:26:43 -07:00
Koushik Dutta
851c5caf4d install: nvidia container toolkit 2024-10-09 12:16:32 -07:00
Koushik Dutta
03cfeffca5 install: nvidia container toolkit 2024-10-09 12:16:22 -07:00
Koushik Dutta
196316ad97 install: support 24.04 containers. remove cudnn8 and cuda11. 2024-10-09 11:11:51 -07:00
Koushik Dutta
f7ccdf0795 Merge branch 'main' of github.com:koush/scrypted 2024-10-09 10:39:57 -07:00
Koushik Dutta
64d36513a0 install: support 24.04 containers. remove cudnn8 and cuda11. 2024-10-09 10:39:52 -07:00
David Montgomery
6ae8fd6d96 update broken link (#1605)
* Update install-scrypted-docker-compose.sh

* Update install-scrypted-docker-compose.sh

---------

Co-authored-by: Koushik Dutta <koush@koushikdutta.com>
2024-10-08 17:34:13 -07:00
Koushik Dutta
7448f19b78 install: Update docker-compose.sh 2024-10-07 19:53:49 -07:00
Koushik Dutta
35f0e325c1 common: strict 2024-10-05 20:53:26 -07:00
Koushik Dutta
579e188d06 diagnostics: logging 2024-10-05 20:53:21 -07:00
Koushik Dutta
09e97a2895 lxc-docker: more system maintenance on startup 2024-10-05 11:56:07 -07:00
Koushik Dutta
700856bc2e reolink: use abs movement 2024-10-05 09:55:00 -07:00
Koushik Dutta
26eb69b08a reolink: publish 2024-10-05 08:56:09 -07:00
Koushik Dutta
332d9716f9 reolink: fix double ptz move 2024-10-05 08:55:35 -07:00
Koushik Dutta
511f348cbe onvif: initial ptz preset support 2024-10-04 20:16:44 -07:00
Koushik Dutta
f26b6c3bca unifi-protect: consider host when trying to find stable ids 2024-10-04 17:23:59 -07:00
Koushik Dutta
d38abcd563 core: ptz preset/home support 2024-10-04 15:41:08 -07:00
Koushik Dutta
b71f6e8b7e onvif: preset support 2024-10-04 15:23:46 -07:00
Koushik Dutta
b492e8912e onvif: continuous movement support 2024-10-04 14:57:29 -07:00
Koushik Dutta
e663f5d3fc lxc-docker: use -e 2024-10-04 13:11:51 -07:00
Koushik Dutta
21ac653c66 core: update ui 2024-10-04 12:06:44 -07:00
Koushik Dutta
e6f80be974 core: support updates for lxc docker 2024-10-04 12:03:07 -07:00
Koushik Dutta
7b41e17981 lxc: remove welcome as it messes up dpkg 2024-10-04 11:53:48 -07:00
Koushik Dutta
530961179d lxc-docker: updates 2024-10-04 11:44:53 -07:00
Koushik Dutta
7bb1d75905 proxmox: fix writing /etc/issue 2024-10-03 14:19:26 -07:00
Koushik Dutta
337a74a170 proxmox: pull the docker compose script from repo 2024-10-03 13:45:25 -07:00
Koushik Dutta
e21facb123 proxmox: add docker compose script 2024-10-03 13:42:28 -07:00
Koushik Dutta
15ac061311 proxmox: add docker compose script 2024-10-03 13:41:31 -07:00
Koushik Dutta
f66a300082 docker: cleanup old installs 2024-10-03 13:33:35 -07:00
Koushik Dutta
24d754b5dc lxc: background the update processes 2024-10-03 13:02:43 -07:00
Koushik Dutta
0221d00a17 lxc: change docker-compose.sh path 2024-10-03 12:56:43 -07:00
Koushik Dutta
3c49501c2c proxmox: lxc icon 2024-10-03 12:50:16 -07:00
Koushik Dutta
a81e5337f0 lxc: fix script creation/chmod order 2024-10-03 11:41:33 -07:00
Koushik Dutta
675339f495 lxc: fix script erorr 2024-10-03 11:36:37 -07:00
Koushik Dutta
48c6b90e21 lxc: more docker env tweaks 2024-10-03 11:35:33 -07:00
Koushik Dutta
ccf2b8c67d lxc-docker: disable autorestart 2024-10-03 10:56:05 -07:00
Koushik Dutta
cc97d7d1c1 docker: disable init core dump anyways 2024-10-03 10:39:02 -07:00
Koushik Dutta
6af2f5eecd docker: another attempt at ulimit 2024-10-03 10:27:13 -07:00
Koushik Dutta
1df4c964d7 lxc-docker: disable watchtower 2024-10-03 10:14:29 -07:00
Koushik Dutta
24b5b36a44 docker: disable core dumps in lite container 2024-10-03 09:24:58 -07:00
Koushik Dutta
1da7d25235 Merge branch 'main' of github.com:koush/scrypted 2024-10-03 09:11:39 -07:00
Koushik Dutta
d691b21646 docker: something enabled core dumps in container. disable core dumps in container. 2024-10-03 09:11:34 -07:00
Brett Jia
d691bfcef1 core: clear local url converter cache after 10m (#1595)
* core: clear local url converter cache after 10s

* update to 10m
2024-10-02 12:15:59 -07:00
Koushik Dutta
04d5633690 nvidia: icd mount no longer necessary 2024-10-02 10:05:57 -07:00
Koushik Dutta
dffd20f978 Merge branch 'main' of github.com:koush/scrypted 2024-10-02 09:39:35 -07:00
Koushik Dutta
5fd9579423 nvidia: icd notes 2024-10-02 09:39:28 -07:00
Koushik Dutta
bd7d49833f nvidia: fix container expectations 2024-10-02 09:38:10 -07:00
Brett Jia
701ca5e1e2 objectdetector: extend retention of detection inputs to 10s (#1586) 2024-10-02 09:30:11 -07:00
Koushik Dutta
14cb5a2117 install: can't fix stupid 2024-10-02 09:23:16 -07:00
Koushik Dutta
adf4e797c1 onnx/nvidia docker: bump versions, fix cuda 12 2024-10-02 09:00:14 -07:00
Koushik Dutta
a946be88d3 onnx: docs 2024-10-01 23:56:21 -07:00
Koushik Dutta
4be844f3f7 onnx: update runtime for windows 2024-10-01 23:51:34 -07:00
Koushik Dutta
9eff813619 Merge branch 'main' of github.com:koush/scrypted 2024-10-01 09:29:36 -07:00
Koushik Dutta
e1b5eaa63f google-device-access: rebuild with new sdk 2024-10-01 09:29:29 -07:00
Koushik Dutta
b7f1efc307 diagnostics: typo 2024-09-30 18:47:42 -07:00
Koushik Dutta
12fedc53ee Merge branch 'main' of github.com:koush/scrypted 2024-09-29 15:19:47 -07:00
Koushik Dutta
1c7626c156 diagnostics: fix nre in server addr check 2024-09-29 15:19:42 -07:00
Koushik Dutta
a578623d3f nvidia: more reliable opencl setup 2024-09-28 12:15:30 -07:00
Koushik Dutta
b13d32f3ed amcrest: publish 2024-09-28 10:46:04 -07:00
Koushik Dutta
d34c3aae74 amcrest: dont fail if motion detect reset fails 2024-09-28 10:45:03 -07:00
Koushik Dutta
c27176f0f8 ring: more push updates 2024-09-26 10:07:05 -07:00
Koushik Dutta
be4f4bb6d6 install: update intel drivers 2024-09-25 21:03:52 -07:00
Koushik Dutta
26db89b811 cloud: observe connection termination 2024-09-25 20:19:44 -07:00
Koushik Dutta
6f0738ef07 diagnostics: gpu transform test 2024-09-25 13:06:34 -07:00
Koushik Dutta
1ae1eafddc diagnostics: add detection test 2024-09-25 12:27:17 -07:00
Koushik Dutta
0ecacfd974 openvino: update openvino to 2014.4.0 2024-09-25 08:56:14 -07:00
Koushik Dutta
146a648f39 snapshot: export createVipsMediaObject 2024-09-25 08:55:40 -07:00
Koushik Dutta
7015f26eee ring: heartbeat 2024-09-24 11:42:15 -07:00
Brett Jia
a4e484698d server: implement python listen + listenDevice (#1587)
* server: implement python listen + listenDevice

* fix unregister

* make functions synchronous
2024-09-23 09:34:10 -07:00
Koushik Dutta
1d659a5fb9 onvif: update onvif to support https, publish 2024-09-22 12:01:56 -07:00
Koushik Dutta
80e70b6bb8 ring: update push receiver 2024-09-22 11:28:55 -07:00
Koushik Dutta
ceec1174e3 cloud: expose server id header 2024-09-20 15:52:12 -07:00
Koushik Dutta
b658202d8a cloud: include server id in responses 2024-09-20 15:45:34 -07:00
Koushik Dutta
425ee41ab0 core: publish 2024-09-20 15:06:11 -07:00
Koushik Dutta
3f7b801ffb cloud: server id reporting 2024-09-20 15:06:07 -07:00
Koushik Dutta
ccb7ae0323 core: publish 2024-09-20 10:06:50 -07:00
Koushik Dutta
252c90fb46 cloud: remove reliance on google for login process 2024-09-19 23:11:04 -07:00
Koushik Dutta
2beceaf869 videoanalysis: provide audio 2024-09-19 20:43:25 -07:00
Koushik Dutta
1dbb9a0f63 Merge branch 'main' of github.com:koush/scrypted 2024-09-19 12:03:03 -07:00
Koushik Dutta
85c35f5fb7 amcrest: autoconfigure removes amcrest logo 2024-09-19 12:02:59 -07:00
Koushik Dutta
8966cd7c70 Update install-scrypted-proxmox.sh 2024-09-19 07:22:44 -07:00
Koushik Dutta
60aeae5336 diagnostics: codec check 2024-09-18 16:14:16 -07:00
Koushik Dutta
eef6c3ed3f cloud: use multiple signaling paths 2024-09-18 10:08:57 -07:00
Koushik Dutta
979c430303 cloud: remove dead code 2024-09-18 08:47:51 -07:00
Koushik Dutta
4892b72f37 cloud: use cloudflare as secondary signaling path 2024-09-17 09:19:14 -07:00
Koushik Dutta
3fd81b86d7 webrtc: wait before terminating thread 2024-09-15 21:51:03 -07:00
Koushik Dutta
b3a2789a1d diagnostics: cloud warn 2024-09-15 21:50:33 -07:00
Koushik Dutta
fde5cfa51e webrtc: remove webrtc api transport 2024-09-15 15:04:14 -07:00
Koushik Dutta
1ada7bb3fe common: rtp forwarder ffmpeg path 2024-09-15 13:26:25 -07:00
Koushik Dutta
2445ea909d proxmox: good grief people cant read 2024-09-15 13:26:15 -07:00
Koushik Dutta
7b16e8e969 install: make sure install is performed on proxmox host 2024-09-15 10:33:38 -07:00
Koushik Dutta
1ffe8357e3 diagnostics: print addresses 2024-09-14 12:55:55 -07:00
Koushik Dutta
c96b4730de Merge branch 'main' of github.com:koush/scrypted 2024-09-14 12:40:14 -07:00
Koushik Dutta
d89a8c6072 diagnostics: indicator for test hang/running 2024-09-14 12:40:09 -07:00
Koushik Dutta
8e47bbb153 proxmox: disk script logging 2024-09-14 10:05:38 -07:00
Koushik Dutta
b04bb414d6 proxmox: better disk granularity 2024-09-13 22:31:43 -07:00
Koushik Dutta
bd947fb934 proxmox: add disk 2024-09-13 22:30:25 -07:00
Koushik Dutta
a643960863 proxmox: disk type support 2024-09-13 22:28:14 -07:00
Koushik Dutta
83f869988d proxmox: script formatting 2024-09-13 22:23:40 -07:00
Koushik Dutta
1fc0934b4e proxmox: script formatting 2024-09-13 22:20:13 -07:00
Koushik Dutta
29b7e4151a proxmox: script formatting 2024-09-13 22:11:24 -07:00
Koushik Dutta
ad3c4f9529 proxmox: script formatting 2024-09-13 22:06:07 -07:00
Koushik Dutta
e9026372c1 Merge branch 'main' of github.com:koush/scrypted 2024-09-13 21:50:27 -07:00
Koushik Dutta
9b30064896 proxmox: dir script 2024-09-13 18:13:19 -07:00
Koushik Dutta
c73ffb30c1 proxmox: docs 2024-09-13 18:03:27 -07:00
Koushik Dutta
bae12eecae proxmox: dir sanity check 2024-09-13 18:00:52 -07:00
Koushik Dutta
1440b3811d proxmox: scripts 2024-09-13 17:58:49 -07:00
Koushik Dutta
59a3a97577 diagnostics: words 2024-09-13 10:54:03 -07:00
Koushik Dutta
07f02fe371 postbeta 2024-09-13 10:53:36 -07:00
Koushik Dutta
cf4f4b7c73 diagnostics: more checks 2024-09-12 20:36:14 -07:00
Koushik Dutta
aab0bdfc41 cloud: additional cloudflare failure handling 2024-09-12 18:47:11 -07:00
Koushik Dutta
438f61b729 lxc: mirror docker compose 2024-09-12 18:46:20 -07:00
Koushik Dutta
0b3717439f lxc: relax chown 2024-09-12 13:51:22 -07:00
Koushik Dutta
a9a145bd3e lxc: relax SCRYPTED_NONINTERACTIVE check 2024-09-12 13:29:53 -07:00
Koushik Dutta
2f97b39cbb lxc: service user is root 2024-09-12 13:28:42 -07:00
Koushik Dutta
8bc1fe1588 lxc: apparmor removal should be allowed to fail 2024-09-12 13:27:59 -07:00
Koushik Dutta
90740f3c9d lxc: remove apparmor 2024-09-12 13:25:41 -07:00
Koushik Dutta
f92a12b99c Merge branch 'main' of github.com:koush/scrypted 2024-09-12 13:23:09 -07:00
Koushik Dutta
405453da03 install: lxc docker prototype 2024-09-12 13:23:04 -07:00
Brett Jia
d01fe4310b server: python createMediaManager func (#1574)
* server: python createMediaManager func

* use api's media manager directly
2024-09-12 13:08:03 -07:00
Koushik Dutta
6bcab63e0e install: lxc docker prototype 2024-09-12 13:01:16 -07:00
Koushik Dutta
c2bf7a62ab install: lxc docker prototype 2024-09-12 12:51:51 -07:00
Koushik Dutta
bc631d6c8b diagnostics: recognize ha 2024-09-12 12:02:10 -07:00
Koushik Dutta
66877d1efa core: i am really bad at this 2024-09-12 11:13:01 -07:00
Koushik Dutta
96a4a11503 core: fix level-zero install check 2024-09-12 11:04:01 -07:00
Koushik Dutta
bd0393305b core: trigger restart after level zero removal 2024-09-12 10:51:26 -07:00
Koushik Dutta
9033eadafb docker: remove npu 2024-09-12 10:50:29 -07:00
Koushik Dutta
c42b8ecda2 openvino/lxc: fix crashing 2024-09-12 10:49:18 -07:00
Koushik Dutta
521bb62f10 openvino: better gpu failure fallback 2024-09-11 16:55:20 -07:00
Koushik Dutta
8819f0a249 install: update intel firmware 2024-09-11 16:54:54 -07:00
Koushik Dutta
341cfa1e2f diagnostics: gpu decode test 2024-09-11 12:53:01 -07:00
Koushik Dutta
96335544ad openvino: openvino 2024.2.0 is crashy 2024-09-11 12:52:38 -07:00
Koushik Dutta
ce0adb5706 diagnostics: skip dupes 2024-09-11 10:44:58 -07:00
Koushik Dutta
22fb257214 core: update ui 2024-09-11 10:28:44 -07:00
Koushik Dutta
674034fb7e openvino: GPU to AUTO fallback on error 2024-09-11 10:13:45 -07:00
Koushik Dutta
44dcfe5e12 openvino: rollback 2024-09-11 10:08:30 -07:00
Koushik Dutta
194e8532c3 core: publish 2024-09-11 09:45:40 -07:00
Koushik Dutta
797ef79080 unifi-protect: filter out unadopted cams 2024-09-11 09:28:10 -07:00
Koushik Dutta
56dbecbf3d videoanalsyis: dont allow extension to be disabled. 2024-09-11 08:57:27 -07:00
Koushik Dutta
67acb7725f openvino: fix model execution 2024-09-10 19:56:42 -07:00
Koushik Dutta
a2caad7109 diagnostics: idr check 2024-09-10 17:43:16 -07:00
Koushik Dutta
599d370f7d diagnostics: unifi protect junk snapshots 2024-09-10 15:23:56 -07:00
Koushik Dutta
be284a0df7 diagnostics: (jsonip.com) 2024-09-10 15:17:02 -07:00
Koushik Dutta
030c3432a7 diagnostics: notifier 2024-09-10 15:16:34 -07:00
Koushik Dutta
7d0d26ad31 diagnostics: install validation 2024-09-10 15:04:23 -07:00
Koushik Dutta
6ba8a1dea4 diagnostics: publish 2024-09-10 14:37:40 -07:00
Koushik Dutta
cafb6944f5 diagnostics: stream validation 2024-09-10 14:34:03 -07:00
Koushik Dutta
f800401317 diagnostics: initial commit 2024-09-10 14:17:19 -07:00
Koushik Dutta
d672e2271d sdk: update 2024-09-10 13:21:54 -07:00
Koushik Dutta
3d558e3119 postbeta 2024-09-09 12:50:33 -07:00
Brett Jia
c94945c6d5 server: allow plugins to specify portable python build tags (#1571) 2024-09-09 12:26:01 -07:00
Koushik Dutta
82afc6d53f ha: update 2024-09-08 16:43:50 -07:00
Koushik Dutta
16ba10da21 videoanalysis: deprecate electron core 2024-09-08 16:43:37 -07:00
Koushik Dutta
6f5e0700a2 postrelease 2024-09-08 16:41:04 -07:00
Koushik Dutta
11b81371b4 postrelease 2024-09-08 16:40:29 -07:00
Koushik Dutta
e33cacd15d postbeta 2024-09-06 10:54:31 -07:00
Koushik Dutta
e225b746c4 server: update deps 2024-09-06 10:54:24 -07:00
Koushik Dutta
1e1fda6b9a server: findPluginDevice is not optional 2024-09-06 10:50:06 -07:00
Koushik Dutta
e23c9c22dc onnx: fix platform check 2024-09-05 10:34:22 -07:00
Koushik Dutta
28f1ce9d4e postbeta 2024-09-04 12:19:33 -07:00
Koushik Dutta
5f4e2793ff server: possibly fix bug where rpc object may not be found 2024-09-04 10:36:56 -07:00
Koushik Dutta
1e1755fa7e server: cluster cleanups 2024-09-04 10:17:30 -07:00
Koushik Dutta
ebd56b86e4 postbeta 2024-09-04 09:30:27 -07:00
Koushik Dutta
4607bec07c server: improve fork/thread logging 2024-09-04 09:30:19 -07:00
Koushik Dutta
a26cdfea2a postbeta 2024-09-03 22:45:04 -07:00
Koushik Dutta
6d0da449ad server: simplify convoluted peer key 2024-09-03 22:31:51 -07:00
Koushik Dutta
ad15fe3324 cloud: update deps 2024-09-03 17:20:39 -07:00
Koushik Dutta
fbe3e83884 cameras: move autoconfiguration button so its less accidentally clickable 2024-09-03 16:01:11 -07:00
Koushik Dutta
0d4cf34930 reolink: move some device creation stuff into advanced tab 2024-09-03 15:54:36 -07:00
Koushik Dutta
3a3e15cd74 server: allow main/child thread ipc 2024-09-03 15:26:21 -07:00
Koushik Dutta
8b9cfebbfa cloud: handle mux carrier errors 2024-09-03 08:43:06 -07:00
Koushik Dutta
b3087058a7 google-home/alexa: republish with new sdk for media converter 2024-09-02 08:40:03 -07:00
Koushik Dutta
4e923a78da cloud: fix short lived regression 2024-09-01 20:42:32 -07:00
Koushik Dutta
b5593d6251 cloud: cleanups 2024-09-01 20:14:47 -07:00
Koushik Dutta
40b7b621a0 openvino: update 2024-09-01 08:17:54 -07:00
Koushik Dutta
7104ad6378 openvino: improve device selection 2024-08-29 21:15:19 -07:00
Koushik Dutta
51f893ef63 install: update proxmox and ha 2024-08-29 20:58:54 -07:00
Koushik Dutta
29c5dfd73b core: install npu drivers in lxc 2024-08-29 20:37:42 -07:00
Koushik Dutta
1615f79a0b install: npu driver update 2024-08-29 20:32:35 -07:00
Koushik Dutta
dc5a6126b9 sdk: add id to recorded event on notifications 2024-08-29 08:02:33 -07:00
Koushik Dutta
0fbe3e4686 cloud: upnp no longer default 2024-08-28 13:23:52 -07:00
Koushik Dutta
c9641568f8 core: publish 2024-08-27 21:54:36 -07:00
Koushik Dutta
dceea38eb8 core: publish 2024-08-27 21:31:22 -07:00
Koushik Dutta
cd1fce71e2 postrelease 2024-08-27 21:15:09 -07:00
Koushik Dutta
3b6454f107 cli: add support for version launch hint 2024-08-27 18:30:33 -07:00
Koushik Dutta
d238d8d4ba onnx: fix broken arm64 2024-08-27 11:16:16 -07:00
Koushik Dutta
a24d46f3d2 postbeta 2024-08-27 09:36:56 -07:00
Koushik Dutta
df7deef4aa server/sdk: forks can be associated with specific device/mixin 2024-08-27 09:36:47 -07:00
Koushik Dutta
e94cea0236 Revert "server: revert port contention change"
This reverts commit 57439634e5.
2024-08-27 08:58:22 -07:00
Koushik Dutta
4794a6dbf3 postbeta 2024-08-27 08:50:28 -07:00
Koushik Dutta
57439634e5 server: revert port contention change 2024-08-27 08:50:19 -07:00
Koushik Dutta
89e6e50b12 rebroadcast: reduce logging 2024-08-26 23:04:51 -07:00
Koushik Dutta
c21ef069bd Merge branch 'main' of github.com:koush/scrypted 2024-08-26 14:18:15 -07:00
Koushik Dutta
5d41bb38da postbeta 2024-08-26 14:18:11 -07:00
Koushik Dutta
b289024083 server: fix fork debugging port contention 2024-08-26 14:18:04 -07:00
Brett Jia
56572bcec9 onnx: fix install on linux arm64 (#1564) 2024-08-26 09:29:51 -07:00
Koushik Dutta
3e78209817 postbeta 2024-08-26 08:55:27 -07:00
Koushik Dutta
299204313f server: use constants for plugin markers 2024-08-26 08:55:19 -07:00
Koushik Dutta
88b134f4b9 postbeta 2024-08-26 08:35:02 -07:00
Koushik Dutta
e8bd72a329 server: fix child process flag markers 2024-08-26 08:34:54 -07:00
Koushik Dutta
214dbc8153 postbeta 2024-08-26 08:12:33 -07:00
Koushik Dutta
3f0c706154 server: improve process markers 2024-08-26 08:12:26 -07:00
Koushik Dutta
013131e816 postbeta 2024-08-25 12:36:57 -07:00
Koushik Dutta
0342bf91f6 server: add rimraf 2024-08-25 12:36:46 -07:00
Koushik Dutta
6fb98c7e84 server: remove legacy deps 2024-08-25 12:36:28 -07:00
Koushik Dutta
f4168ff4eb postbeta 2024-08-25 09:58:02 -07:00
Koushik Dutta
a5febd7ca0 server: update deps 2024-08-25 09:57:55 -07:00
Koushik Dutta
31428b4c28 postbeta 2024-08-24 18:21:21 -07:00
Koushik Dutta
3e0dfc6bda install: remove electron 2024-08-24 18:12:44 -07:00
Koushik Dutta
4290eb0abb server: remove electron 2024-08-24 18:12:00 -07:00
Koushik Dutta
fd2d7e9485 server: electron angle setup 2024-08-24 18:10:05 -07:00
Koushik Dutta
a57cf3b1e6 sdk: improve multi entry build 2024-08-24 18:09:50 -07:00
Koushik Dutta
fad485c0d7 Merge branch 'main' of github.com:koush/scrypted 2024-08-23 08:22:41 -07:00
Koushik Dutta
9e3cf83b07 onnx: fix broken onnxruntime-gpu cudnn9 2024-08-23 08:22:35 -07:00
Koushik Dutta
ebe0b6ea7f install: remove intel stuff from lite builds 2024-08-22 16:22:17 -07:00
Koushik Dutta
4ce0ecaaa2 onvif: fix autoconfig with no audio 2024-08-22 12:33:42 -07:00
Koushik Dutta
44264fb50b onnx: make cuda available to windows 2024-08-22 10:27:12 -07:00
Koushik Dutta
ab188bfe80 postbeta 2024-08-21 14:34:05 -07:00
Koushik Dutta
83d32da7f1 server: improve electron enable-features handling 2024-08-21 14:33:57 -07:00
Koushik Dutta
e68b3f401f postbeta 2024-08-21 14:02:44 -07:00
Koushik Dutta
43a73c6d89 server: fix electron bin in npm package 2024-08-21 14:02:12 -07:00
Koushik Dutta
6c6613d841 server: fixup electron bin dir path per platform/version 2024-08-21 14:00:57 -07:00
Koushik Dutta
479ef136a6 postbeta 2024-08-21 13:41:41 -07:00
Koushik Dutta
b42abf377b server: use @electron/get as production dependency 2024-08-21 13:41:05 -07:00
Koushik Dutta
5713935ccc server: break out electron runtimes 2024-08-21 12:51:23 -07:00
Koushik Dutta
09fc609c7f postbeta 2024-08-21 12:22:36 -07:00
Koushik Dutta
e44ba222b8 server: fix convertMediaObjectToJSON back compat 2024-08-21 12:18:30 -07:00
Koushik Dutta
e34a5a7c3d snapshot: fix perma broken nvr snapshots 2024-08-21 12:03:29 -07:00
Koushik Dutta
e490225c4a webrtc: simplify convert paths 2024-08-21 11:50:25 -07:00
Koushik Dutta
e769e8ea98 sdk: remove unnecessary param in debug request 2024-08-21 11:50:00 -07:00
Koushik Dutta
ec5c164552 webrtc: fix type erasure 2024-08-21 11:31:54 -07:00
Koushik Dutta
64a213424d postbeta 2024-08-21 11:10:53 -07:00
Koushik Dutta
e81c454c1e server: fix node thread worker removing handlers that should not be 2024-08-21 11:10:21 -07:00
Koushik Dutta
776307bcbc server: enable SharedArrayBuffer and other stuff for electron 2024-08-21 11:09:31 -07:00
Koushik Dutta
95c97e3eb2 server: fix plugin load causing server crash, fix unhandled rejections caused by plugin kill 2024-08-21 10:59:27 -07:00
Koushik Dutta
08926a35a9 server: use standard debug port for electron 2024-08-21 10:43:51 -07:00
Koushik Dutta
c037548ffb postbeta 2024-08-21 09:52:45 -07:00
Koushik Dutta
462189efc2 server: implement electron debugging 2024-08-21 09:50:22 -07:00
Koushik Dutta
a4fed9c7ad postbeta 2024-08-20 23:20:13 -07:00
Koushik Dutta
3c8f94ab2f server: Fix electron display var 2024-08-20 23:20:04 -07:00
Koushik Dutta
fe3391c89c docker: fix xvfb dep 2024-08-20 22:51:24 -07:00
Koushik Dutta
270b43bed6 postbeta 2024-08-20 22:23:07 -07:00
Koushik Dutta
c0fe12827f server: hide electron window 2024-08-20 22:22:59 -07:00
Koushik Dutta
3bbda53107 postbeta 2024-08-20 22:21:23 -07:00
Koushik Dutta
0d7ee00485 server: electron wip 2024-08-20 22:21:09 -07:00
Koushik Dutta
c605c3ddb5 server: update deps 2024-08-20 20:50:02 -07:00
Koushik Dutta
099ba4f081 server: organize 2024-08-20 20:49:48 -07:00
Koushik Dutta
c14487ac27 server: remove deno 2024-08-20 20:49:23 -07:00
Koushik Dutta
991c31dda8 install: electron deps 2024-08-20 20:35:26 -07:00
Koushik Dutta
3865efd1f7 postbeta 2024-08-19 17:54:18 -07:00
Koushik Dutta
9c5ce45c1e server: catch unhandled iterator teardown throwups 2024-08-19 17:54:08 -07:00
Koushik Dutta
4ab7bc1298 postbeta 2024-08-19 16:04:47 -07:00
Koushik Dutta
0ebbc5ea8f server: sketchy check to determine if buffer is pool buffer 2024-08-19 16:04:38 -07:00
Koushik Dutta
86dcb66e6a postbeta 2024-08-19 15:51:34 -07:00
Koushik Dutta
11831e5d87 server: rpc should handle transport serialization failures and attempt to send plain objects with the error 2024-08-19 15:50:32 -07:00
Koushik Dutta
6b3dc8c1ae postbeta 2024-08-19 13:24:42 -07:00
Koushik Dutta
a49256f073 server: already connected ipc object fast path 2024-08-19 13:24:35 -07:00
Koushik Dutta
ea408377ec postbeta 2024-08-19 13:20:28 -07:00
Koushik Dutta
2da762dfc2 server: working transferible buffers 2024-08-19 13:20:21 -07:00
Koushik Dutta
bfbc6ba6ce rebroadcast: fix build 2024-08-19 12:02:45 -07:00
Koushik Dutta
c2747c80dc server: consolidate peer thread setup 2024-08-19 11:43:10 -07:00
Koushik Dutta
2b58de196e server: use ipc for node threads 2024-08-19 11:07:13 -07:00
Koushik Dutta
731744afbc server: warn on base64 serialization 2024-08-19 09:47:51 -07:00
Koushik Dutta
f4d88493b1 postbeta 2024-08-18 12:47:35 -07:00
Koushik Dutta
265fc4b481 Merge branch 'main' of github.com:koush/scrypted 2024-08-18 12:47:06 -07:00
Koushik Dutta
40a300cff1 server: update console logging location to accomodate vscode filters 2024-08-18 12:47:00 -07:00
Brett Jia
c410907c58 webrtc: remove missing var (#1562) 2024-08-17 23:21:16 -07:00
Brett Jia
199f333fc1 server: allow all application/* mime types (#1561) 2024-08-17 23:21:04 -07:00
Brett Jia
e39bc8c5e6 core: terminal paths via TTYSettings + add TTY interface (#1559) 2024-08-17 16:39:00 -07:00
Brett Jia
a55099de12 webrtc: convert RTCSignalingChannel to FFmpegInput + consolidate all converters (#1558)
* webrtc: add converter from RTCSignalingChannel to FFmpegInput

* consolidate buffer converters to WebRTCBridge as MediaConverter

* consolidate all converters into base plugin device

* remove unused
2024-08-17 10:31:15 -07:00
Koushik Dutta
17900f0589 sdk: fix excessive zipping 2024-08-16 20:32:08 -07:00
Koushik Dutta
075d8bc4ab snapshot: log prebuffer unavailable error 2024-08-16 19:25:41 -07:00
Koushik Dutta
28fce1bb8b Merge branch 'main' of github.com:koush/scrypted 2024-08-16 08:57:22 -07:00
Koushik Dutta
14a2790825 sdk: parallelize build 2024-08-16 08:57:18 -07:00
Roman Sokolov
c2cd491c96 Hikvision Doorbell (#1557)
* Fixed reconnection bugs

* Updated documentation

* hikvision-doorbell version up

* Added support for contact sensor (if it installed on door)

* Refactoring doorbell api

* Fixed some bugs in hikvision doorbell
2024-08-15 15:24:46 -07:00
Koushik Dutta
6301089620 postbeta 2024-08-14 20:28:40 -07:00
Koushik Dutta
c591a87015 server: scope deno into module package 2024-08-14 20:28:33 -07:00
Koushik Dutta
544700ac12 postbeta 2024-08-14 20:22:17 -07:00
Koushik Dutta
2c54dc07ae server: use js for deno-plugin-remote 2024-08-14 20:22:11 -07:00
Koushik Dutta
0dad6eaa76 postbeta 2024-08-14 19:33:11 -07:00
Koushik Dutta
d18b8e0694 server: fix deno stdout 2024-08-14 19:33:03 -07:00
Koushik Dutta
a4130ed047 coreml: update project files 2024-08-14 19:31:52 -07:00
Koushik Dutta
1f89dcb34c common: fix zygote signature 2024-08-14 19:31:31 -07:00
Koushik Dutta
e86ed47533 sdk: fix node import 2024-08-14 13:21:14 -07:00
Koushik Dutta
5fb75e351d postbeta 2024-08-14 12:11:32 -07:00
Koushik Dutta
8ef3fe7a24 server: add support for cross language fork 2024-08-14 11:14:13 -07:00
Koushik Dutta
5c8f034d7c postbeta 2024-08-14 08:43:02 -07:00
Koushik Dutta
561852bc15 server: fixup python remote debugging, fs chdir locations 2024-08-14 08:42:55 -07:00
Koushik Dutta
d14c592d55 vscode-python: proper remote debug fix 2024-08-14 08:33:30 -07:00
Koushik Dutta
bc439d6b7c postbeta 2024-08-14 08:22:55 -07:00
Koushik Dutta
aedb4212fe postbeta 2024-08-14 08:16:43 -07:00
Koushik Dutta
7b780a0eb9 postbeta 2024-08-13 23:21:12 -07:00
Koushik Dutta
6aaaccaece server: revert back to original change that conditionally added unzipped path 2024-08-13 23:21:05 -07:00
Koushik Dutta
0e42b71e4b server: fixup python requirements calc 2024-08-13 23:14:26 -07:00
Koushik Dutta
71a6f9d6a6 vscode-python: revert 2024-08-13 23:03:54 -07:00
Koushik Dutta
68c77aaca4 postbeta 2024-08-13 22:51:41 -07:00
Koushik Dutta
4b73c168b3 vscode-python: update sample with normalized paths 2024-08-13 22:51:18 -07:00
Brett Jia
8f4b67dc5c server: add unzipped path to python module lookup path (#1553)
* server: add unzipped path to python module lookup path

* remove zipPath from sys.path
2024-08-13 22:46:57 -07:00
Koushik Dutta
8a8bee33c1 server: normalize fs path 2024-08-13 22:45:51 -07:00
Koushik Dutta
2b353cf4c8 Merge branch 'main' of github.com:koush/scrypted 2024-08-13 20:13:11 -07:00
Koushik Dutta
6d9cd45936 rebroadcast: add global audio soft mute 2024-08-13 20:13:03 -07:00
Brett Jia
0bc6fadb23 server: allow plugins to customize python installs (#1542)
* server: allow plugins to customize python installs

* move options inside pythonVersion
2024-08-13 18:18:39 -07:00
Koushik Dutta
407f573a29 server: better ipv6 filtering 2024-08-13 12:03:24 -07:00
Koushik Dutta
39674ef9b6 server: fix backup 2024-08-13 10:58:11 -07:00
Koushik Dutta
ffaed01dc3 server: update types 2024-08-13 10:40:49 -07:00
Koushik Dutta
9a144a9a05 postbeta 2024-08-13 10:39:47 -07:00
Koushik Dutta
76e63120f0 server: remove ip dependency for custom implementation 2024-08-13 10:39:37 -07:00
Koushik Dutta
154bc6fef7 postbeta 2024-08-13 10:38:56 -07:00
Koushik Dutta
8302c564c2 cameras: fix autoconfigure math 2024-08-13 09:36:54 -07:00
Koushik Dutta
affda9e94f server: fix anonymous auth + backup/deploy 2024-08-13 09:07:42 -07:00
Koushik Dutta
30148f453c postbeta 2024-08-13 09:07:22 -07:00
Koushik Dutta
259313c454 tensorflow-lite: default model 2024-08-12 21:18:59 -07:00
Koushik Dutta
4f82d49f15 tflite: yolov10 2024-08-12 20:51:06 -07:00
Koushik Dutta
a0b7fc54de cameras: autoconfiguration menu fixes 2024-08-12 17:59:00 -07:00
Koushik Dutta
5501093ff9 core: publish 2024-08-12 12:29:17 -07:00
Koushik Dutta
b2622d92f2 cameras: fix auto config error reporting 2024-08-12 12:26:02 -07:00
Koushik Dutta
957bf742d9 hikvision: auto configure should handle model without audio 2024-08-12 07:50:09 -07:00
Koushik Dutta
b06a3ac55f cameras: dont run configuration in parallel due to race conditions in camera side 2024-08-11 22:20:59 -07:00
Koushik Dutta
9c195594ea webrtc: betas 2024-08-11 21:54:30 -07:00
Koushik Dutta
d32efd6500 amcrest: ad410 autoconfigure fixes 2024-08-11 19:31:01 -07:00
Koushik Dutta
03f1957739 hikvision: ignore vca resource failure 2024-08-11 18:59:59 -07:00
Koushik Dutta
94f564a218 onvif: fix tapo 2024-08-11 18:20:38 -07:00
Koushik Dutta
286aa61a18 hikvision: autoconfigure should disable vca resource 2024-08-11 17:58:44 -07:00
Koushik Dutta
43d30a91f9 cameras: publish autoconfiguration 2024-08-11 17:34:18 -07:00
Koushik Dutta
7be81ab7e2 cameras: more configuration cleanups 2024-08-11 17:31:48 -07:00
Koushik Dutta
31c7c9d86a hikvision: fixup fps calc 2024-08-11 14:26:57 -07:00
Koushik Dutta
820c66311d cameras: autoconfiguration notes 2024-08-11 13:59:27 -07:00
Koushik Dutta
84cbe28a47 Merge branch 'main' of github.com:koush/scrypted 2024-08-11 13:54:40 -07:00
Koushik Dutta
cad1cdd5ce core: publish pending ui changes 2024-08-11 13:54:36 -07:00
Koushik Dutta
2a624a95e5 server: import type for acl for peer dependencies 2024-08-11 13:11:07 -07:00
Koushik Dutta
c6d8333402 reolink: add onvif two way option 2024-08-11 12:25:27 -07:00
Koushik Dutta
96dbb1776c Merge branch 'main' of github.com:koush/scrypted 2024-08-11 11:40:12 -07:00
Koushik Dutta
b43a002650 rebroadcast: fix content base handling when it is a relative path 2024-08-11 11:40:07 -07:00
Koushik Dutta
a58d66d484 docker: use noatime for nvr mounts 2024-08-11 07:59:51 -07:00
Koushik Dutta
bcc9be62e9 reolink: update stream config with docs info and publish 2024-08-11 00:58:34 -07:00
Koushik Dutta
38dd9e2ee2 amcrest: motion reset/setup 2024-08-10 23:56:21 -07:00
Koushik Dutta
3033cd9626 cameras: add autoconfiguration alert 2024-08-10 23:10:05 -07:00
Koushik Dutta
12273b7d1e reolink: fix buikd 2024-08-10 22:46:32 -07:00
Koushik Dutta
afe1421c39 cameras: remove unnecessary codec calls 2024-08-10 22:45:00 -07:00
Koushik Dutta
a9fdb71402 onvif: audio autoconfiguration 2024-08-10 20:26:42 -07:00
Koushik Dutta
9cac4cfd18 hikvision: audio codec configuration 2024-08-10 18:41:20 -07:00
Koushik Dutta
fbaf9b97aa amcrest: auto configure audio 2024-08-10 17:58:56 -07:00
Koushik Dutta
0a55732919 server: fix basic auth handling for demo site 2024-08-10 17:37:30 -07:00
Koushik Dutta
ece0ecbd8f postbeta 2024-08-10 17:37:21 -07:00
Koushik Dutta
d2743465c3 Merge branch 'main' of github.com:koush/scrypted 2024-08-10 15:19:02 -07:00
Koushik Dutta
e41af930c5 server: fix basic auth handling for demo site 2024-08-10 15:18:59 -07:00
Koushik Dutta
582b5182e6 postbeta 2024-08-10 15:18:50 -07:00
Koushik Dutta
2b85aa0f27 intel: fix derp 2024-08-10 14:42:59 -07:00
Koushik Dutta
e74e0b7e21 common: missing file for mp3 handling 2024-08-10 14:17:51 -07:00
Koushik Dutta
70d6813938 rebroadcast/webrtc: fix mp3 handling 2024-08-10 14:17:07 -07:00
Koushik Dutta
c1d84d6e08 amcrest: wip auto configure 2024-08-10 11:06:12 -07:00
Koushik Dutta
5c69c70013 amcrest: wip auto configure 2024-08-10 10:36:26 -07:00
Koushik Dutta
6379aa89ef hikvision: wip autoconfigure 2024-08-09 21:39:43 -07:00
Koushik Dutta
c2756a3a4a hikvision: wip codec configuration 2024-08-09 13:32:22 -07:00
Koushik Dutta
303ced735a cameras: wip codec configuration 2024-08-09 13:15:07 -07:00
Koushik Dutta
bc70803cc0 cameras: wip codec configuration 2024-08-09 10:35:09 -07:00
Koushik Dutta
171b04f267 sdk: Update video stream configuration return type 2024-08-09 09:58:11 -07:00
Koushik Dutta
1cd5c194cc cameras: wip codec configuration 2024-08-08 23:06:50 -07:00
Koushik Dutta
c15fe4281e common: fix auth http body 2024-08-08 21:56:58 -07:00
Koushik Dutta
1bd7f37041 cloud: update push library 2024-08-08 21:56:43 -07:00
Koushik Dutta
170bc5f6ad Merge branch 'main' of github.com:koush/scrypted 2024-08-08 21:30:27 -07:00
Koushik Dutta
8daf74e6db cloud: fix cloudflare unregister 2024-08-08 21:30:22 -07:00
Koushik Dutta
b84adf514e docker: fix hw decode 2024-08-08 17:35:40 -07:00
Roman Sokolov
947aa151a5 Fixed some bugs (#1547)
* Fixed reconnection bugs

* Updated documentation

* hikvision-doorbell version up

---------

Co-authored-by: Roman Sokolov <calm@adguard.com>
2024-08-08 09:24:06 -07:00
Koushik Dutta
12c734fe1b cloud: update cloudflared 2024-08-06 20:44:41 -07:00
Koushik Dutta
724b9332f4 Merge branch 'main' of github.com:koush/scrypted 2024-08-06 20:20:59 -07:00
Koushik Dutta
a1f90607af webrtc: publish with werift race fixes 2024-08-06 20:20:54 -07:00
Koushik Dutta
1a954cc232 deferred: publish 2024-08-06 18:11:29 -07:00
Brett Jia
22cb23a075 rknn: show model name + clean up detection classes (#1545) 2024-08-06 14:13:08 -07:00
Koushik Dutta
608f82cf81 detect: proper model name 2024-08-06 13:33:22 -07:00
Koushik Dutta
2f4608e697 Merge branch 'main' of github.com:koush/scrypted 2024-08-06 10:21:10 -07:00
Koushik Dutta
c08ce3115a webrtc: fix non-trickle negotiation 2024-08-06 10:21:02 -07:00
Koushik Dutta
470c28d6ef homekit: reduce debug hksv duration because people keep filling their disks. 2024-08-06 08:25:44 -07:00
David Montgomery
7ea1d8e85d fix typo (#1544) 2024-08-06 07:08:32 -07:00
Koushik Dutta
1669438312 webrtc: publish 2024-08-05 18:48:25 -07:00
Koushik Dutta
d4b77cac66 proxmox: wip restore rootfs 2024-08-05 18:48:22 -07:00
Koushik Dutta
f1bebd0612 proxmox: wip reset/restore preserving data 2024-08-05 00:33:54 -07:00
Koushik Dutta
003e1f79f0 Revert "proxmox: fix --force hint"
This reverts commit 35cf9f9352.
2024-08-04 23:41:23 -07:00
Koushik Dutta
97702da9ef Merge branch 'main' of github.com:koush/scrypted 2024-08-04 23:39:49 -07:00
Koushik Dutta
35cf9f9352 proxmox: fix --force hint 2024-08-04 23:39:45 -07:00
Koushik Dutta
5225823e8b webrtc: publish 2024-08-04 22:40:46 -07:00
Brett Jia
2569e7c823 sdk: add TTYSettings (#1540)
* sdk: add TerminalSettings

* update to TTYSettings
2024-08-04 21:01:34 -07:00
Koushik Dutta
aa5c4d5064 webrtc: update deps, update zygote invocation. 2024-08-04 21:00:39 -07:00
Koushik Dutta
40ff2a8315 postbeta 2024-08-04 13:45:04 -07:00
Koushik Dutta
bf150712a0 proxmox: flowerbox reboot 2024-08-04 13:37:04 -07:00
Koushik Dutta
92531ff675 proxmox: fix detection 2024-08-04 13:36:05 -07:00
Koushik Dutta
6919c26311 proxmox/docker: host reboot notice 2024-08-04 13:08:43 -07:00
Koushik Dutta
f19c09f239 proxmox: uninstall previous npu per intel docs 2024-08-04 12:47:59 -07:00
Koushik Dutta
7cadb8ffac proxmox: npu driver install support 2024-08-04 12:39:47 -07:00
Koushik Dutta
ea204b24a6 docker/lxc: allow installing the npu fw with flag 2024-08-04 12:32:14 -07:00
Koushik Dutta
45799362ce docker: install npu 2024-08-04 12:20:22 -07:00
Koushik Dutta
2836e10262 docker: npu fw should not be installed in container 2024-08-04 12:18:03 -07:00
Koushik Dutta
a04d463e0f docker/proxmox: add/update intel gpu and npu scripts 2024-08-04 12:17:30 -07:00
Koushik Dutta
3ce8a57daa install: update intel graphics 2024-08-04 11:59:12 -07:00
Koushik Dutta
1647c73375 sdk: fix python generation, publish 2024-08-04 09:29:19 -07:00
Koushik Dutta
b7980b7cbf server: worker pid cleanup 2024-08-04 00:28:42 -07:00
Koushik Dutta
0a6114cc60 server: fix deno kill 2024-08-04 00:26:23 -07:00
Koushik Dutta
149675cfb3 server: fix closure capture 2024-08-04 00:24:57 -07:00
Koushik Dutta
b8eec159bc server: revert and use a global shim 2024-08-04 00:14:59 -07:00
Koushik Dutta
ddb93b28cd Revert "server: use function constructor rather than eval"
This reverts commit 4ed6d1a9fd.
2024-08-04 00:02:13 -07:00
Koushik Dutta
4ed6d1a9fd server: use function constructor rather than eval 2024-08-03 23:42:53 -07:00
Koushik Dutta
bd60e39b24 server: fix deno console 2024-08-03 20:42:43 -07:00
Koushik Dutta
b6636b10f0 sdk: update 2024-08-03 17:26:14 -07:00
Koushik Dutta
8c8beea2eb server: add deno flags 2024-08-03 17:14:50 -07:00
Koushik Dutta
3592a98f2a sdk: update typescript 2024-08-03 17:14:36 -07:00
Koushik Dutta
56f8418d13 postbeta 2024-08-03 10:34:16 -07:00
Koushik Dutta
5bb8ea0f86 server: deno runtime 2024-08-03 10:30:31 -07:00
Koushik Dutta
daddf10035 server: organize imports 2024-08-03 10:29:49 -07:00
Koushik Dutta
2ac8e1509d server: use globalThis rather than global 2024-08-03 10:25:55 -07:00
Koushik Dutta
3cd3208183 server: cpuUsage not available on deno 2024-08-03 10:25:00 -07:00
Koushik Dutta
be217021a2 rpc: remove usage of vm module, embed filename using sourceURL 2024-08-03 10:22:24 -07:00
Koushik Dutta
a2bbb67670 rpc: use globalThis rather than global 2024-08-03 10:21:49 -07:00
Koushik Dutta
465189f4b8 proxmox: add npu 2024-08-03 00:16:37 -07:00
Koushik Dutta
173f7fa4f6 core: publish 2024-08-02 13:56:43 -07:00
Koushik Dutta
d405232d81 server: fix wacky import 2024-08-02 13:45:14 -07:00
Koushik Dutta
673fd95bbd common: remove import 2024-08-01 13:37:06 -07:00
Koushik Dutta
25b2a663c8 server: fix nre in fork 2024-08-01 13:37:01 -07:00
Koushik Dutta
962ecf2cae common: fix zygote opts 2024-08-01 13:28:00 -07:00
Koushik Dutta
4c3f1c43fa server: finish fork filename implementation; 2024-08-01 13:27:46 -07:00
Koushik Dutta
82dfa96699 sdk: support multiple entry points for faster forks 2024-08-01 13:27:31 -07:00
Koushik Dutta
83d3add41a reolink: publish 2024-08-01 12:06:38 -07:00
Koushik Dutta
54db7dc64e server: clustering comments 2024-07-31 22:56:38 -07:00
Koushik Dutta
4c04e9e403 server: implement multi server clustering 2024-07-31 22:51:56 -07:00
Koushik Dutta
de44217f65 core: Fix notificaiton automation 2024-07-31 21:06:22 -07:00
Koushik Dutta
3ae6079615 rebroadcast: publish 2024-07-31 20:29:31 -07:00
Koushik Dutta
3f3409ef1b cloud: publish 2024-07-31 20:27:22 -07:00
Koushik Dutta
fd90b8d5f0 cloud: new cloudflare login flow 2024-07-31 14:14:24 -07:00
Koushik Dutta
782c9930da Merge branch 'main' of github.com:koush/scrypted 2024-07-30 22:49:44 -07:00
Koushik Dutta
d0b46c35a9 server/sdk: wip support for alternative fork main, fork names. add initial workerData message channel. 2024-07-30 22:48:52 -07:00
Koushik Dutta
6c7671dc21 server: fix plugin/thread startup messages 2024-07-30 22:34:59 -07:00
Koushik Dutta
bdc3c204d4 reolink: fix speed 2024-07-30 20:51:57 -07:00
Koushik Dutta
2013830677 reolink: enable speed arg 2024-07-30 16:00:33 -07:00
Koushik Dutta
95906a9ed5 reolink: enable speed arg 2024-07-30 15:59:52 -07:00
Koushik Dutta
6fdd4bd0f4 core: publish ui changes 2024-07-30 11:06:50 -07:00
Koushik Dutta
37cf7aada0 common: remove main thread limitation on zygote 2024-07-30 09:11:07 -07:00
Koushik Dutta
dfdc41626b server: properly handle worker errors 2024-07-30 09:10:42 -07:00
Koushik Dutta
237b3ce0d9 server: cleanup message port references and errors 2024-07-30 08:49:21 -07:00
Koushik Dutta
05745bf3c5 server: use node worker message channel so fork can create forks. 2024-07-30 08:40:46 -07:00
Koushik Dutta
8a6eaa5389 postbeta 2024-07-29 21:38:29 -07:00
Koushik Dutta
7ed298139d coreml: revert changes, require min macos version 2024-07-29 19:17:25 -07:00
Koushik Dutta
82908b82c0 server: enable stable cluster proxyIds 2024-07-29 18:34:18 -07:00
Koushik Dutta
946d88236c rebroadcast: beta 2024-07-29 14:25:30 -07:00
Koushik Dutta
1aa1df885d server: fix connectRPCObject gc race condition 2024-07-29 13:43:52 -07:00
Koushik Dutta
7c94ed9b50 coreml: remove ocr on intel 2024-07-28 22:24:44 -07:00
Koushik Dutta
f7dbff4753 coreml: fix intel mac on catalina 2024-07-28 19:05:42 -07:00
Koushik Dutta
00b5e762a7 webrtc: publish beta 2024-07-28 15:43:54 -07:00
Koushik Dutta
e1440eb76f openvino: use smarter defaults based on detected gpu 2024-07-28 12:19:22 -07:00
Brett Jia
4adb8e4202 server: implement python WritableDeviceState (#1537) 2024-07-28 11:35:27 -07:00
Koushik Dutta
e870370d0c webrtc: sync upstream 2024-07-27 20:35:04 -07:00
Koushik Dutta
f944b76c1f core: admin note on users 2024-07-27 10:44:01 -07:00
Koushik Dutta
62543bdfcf webrtc: fix build 2024-07-26 17:46:25 -07:00
Koushik Dutta
447a321eb7 client: admin flag 2024-07-26 17:45:41 -07:00
Koushik Dutta
d094934bd9 tapo: publish http auth fix 2024-07-26 11:08:39 -07:00
Koushik Dutta
c4f8959072 core: publish 2024-07-26 10:32:55 -07:00
Koushik Dutta
d682bd2ebb reolink: reset siren state 2024-07-26 08:28:53 -07:00
Koushik Dutta
437ab70cd9 homekit: update hap, remove siren from auto sync. 2024-07-26 08:28:25 -07:00
Koushik Dutta
15031cde1f reolink: fix comment 2024-07-26 08:01:13 -07:00
Koushik Dutta
e88008552c reolink: make siren timeout mimic hardware 2024-07-26 08:00:38 -07:00
Koushik Dutta
fd49deefb8 postbeta 2024-07-25 21:56:15 -07:00
Koushik Dutta
1f2973abd2 server: fix plugin deploy when SCRYPTED_DEFAULT_AUTHENTICATION is used 2024-07-25 21:56:03 -07:00
Koushik Dutta
317cd7671f server: fix build 2024-07-25 21:45:44 -07:00
Koushik Dutta
9556efc224 server: update deps, print entire stack on uncaught error 2024-07-25 21:44:10 -07:00
Koushik Dutta
2f9db83868 security: make default listen occur on loopback 2024-07-25 21:06:35 -07:00
Koushik Dutta
c627832ebd security: require explicit address on all server listens 2024-07-25 20:54:47 -07:00
Koushik Dutta
7d2df3af42 security: require explicit address on all server listens 2024-07-25 18:33:16 -07:00
Koushik Dutta
e9288bd4a1 core: publish 2024-07-25 18:32:49 -07:00
Koushik Dutta
191620b55b Merge branch 'main' of github.com:koush/scrypted 2024-07-23 09:22:19 -07:00
Koushik Dutta
90b6fc1e49 core/mqtt: scripting fixes 2024-07-23 09:22:15 -07:00
Koushik Dutta
cd3c748dd0 core: automation builder fixes 2024-07-23 09:18:15 -07:00
Koushik Dutta
34dbc7930e tapo: fix 2 way 2024-07-22 17:40:33 -07:00
Koushik Dutta
112633a776 core: various ui fixes 2024-07-22 14:57:13 -07:00
Koushik Dutta
56416109b1 core: more automation actions 2024-07-21 21:45:32 -07:00
Koushik Dutta
a889abae98 core: notifier support 2024-07-21 15:09:38 -07:00
Koushik Dutta
dcb50ba3ff ring: fix h264 assumption 2024-07-21 10:55:33 -07:00
Koushik Dutta
3c61ddb806 core: publish autoupdate fixes 2024-07-21 10:30:42 -07:00
Koushik Dutta
2a9aba1df8 plugins: publish various 2024-07-21 09:56:32 -07:00
Koushik Dutta
450acbdcb1 Merge branch 'main' of github.com:koush/scrypted 2024-07-21 08:25:42 -07:00
Koushik Dutta
80aff3199a webhook: readme 2024-07-21 08:25:37 -07:00
Brett Jia
834eff20c7 sdk, rebroadcast: support specifying custom ffmpeg path (#1535) 2024-07-21 07:31:26 -07:00
Koushik Dutta
6314f5e45a core: publish 2024-07-20 22:37:48 -07:00
Koushik Dutta
5b3793e810 Merge branch 'main' of github.com:koush/scrypted 2024-07-20 22:20:09 -07:00
Koushik Dutta
9a2bff48c5 core: publish 2024-07-20 22:19:41 -07:00
Brett Jia
aa9903b328 sdk, rebroadcast: don't automatically prebuffer synthetic streams (#1534) 2024-07-20 21:05:47 -07:00
Koushik Dutta
c1f4ae96fa core/rtsp: fix settings bugs 2024-07-20 21:01:17 -07:00
Koushik Dutta
d5995d93e2 Merge branch 'main' of github.com:koush/scrypted 2024-07-20 20:56:04 -07:00
Koushik Dutta
f13844cf3e homekit: publish 2024-07-20 20:56:00 -07:00
Brett Jia
6d7add8272 rebroadcast: support env vars + upstream encoder args (#1533)
* rebroadcast: support env vars + upstream encoder args

* make ffmpegInput override process.env

* make h264EncoderArguments safer

* reorder

* update per feedback
2024-07-20 19:53:22 -07:00
Koushik Dutta
983a683d54 ring: clip support 2024-07-20 15:11:55 -07:00
Koushik Dutta
f3e5cf2a8b core: publish new ui 2024-07-20 14:26:09 -07:00
Koushik Dutta
40db551799 Merge branch 'main' of github.com:koush/scrypted 2024-07-20 14:17:11 -07:00
Koushik Dutta
fdb9e03656 core: publish new ui 2024-07-20 14:17:07 -07:00
Brett Jia
48976b2947 sdk: add env to FFmpegInput + fix python parameterized class generator (#1532)
* sdk: add env to FFmpegInput + fix python parameterized class generator

* downgrade node for gh actions
2024-07-20 13:29:45 -07:00
Koushik Dutta
3ee022c2be core: beta 2024-07-19 23:16:55 -07:00
Koushik Dutta
ab24a61fd3 cameras: update with fixed http auth 2024-07-19 19:53:42 -07:00
Koushik Dutta
8d2237b26f Merge branch 'main' of github.com:koush/scrypted 2024-07-19 17:52:12 -07:00
Koushik Dutta
8ad05bbd5b snapshot: ensure hwaccel none for single frame decodes 2024-07-19 17:52:07 -07:00
Koushik Dutta
7499e79dc7 server: suppress WWW-authenticate 2024-07-19 17:11:24 -07:00
Koushik Dutta
7132278204 common: improve stream end errors 2024-07-19 15:18:13 -07:00
Koushik Dutta
60fa494ed0 Merge branch 'main' of github.com:koush/scrypted 2024-07-19 13:17:57 -07:00
Koushik Dutta
815f204136 core: beta 2024-07-19 10:15:10 -07:00
slyoldfox
fe80fab811 Add more meaningful device DeviceInformation for new UI (#1531) 2024-07-19 09:45:11 -07:00
Koushik Dutta
2699ecd93d core: fix empty automation, rebuild ui 2024-07-18 19:01:23 -07:00
Koushik Dutta
5d634f5876 core: new management console beta 2024-07-18 11:13:17 -07:00
Koushik Dutta
9979789e08 zwave: remove legacy dep 2024-07-18 10:39:51 -07:00
Koushik Dutta
79d2d4e366 zwave: remove legacy dep 2024-07-18 10:37:55 -07:00
Koushik Dutta
90b4bcfec9 actions: fixup static sites workflow 2024-07-18 10:27:37 -07:00
Koushik Dutta
49df286cfa Create static.yml 2024-07-18 10:24:51 -07:00
Koushik Dutta
20edf8a622 move static sites 2024-07-18 10:24:34 -07:00
Koushik Dutta
bb76102171 cloud: fix bug where port reservation failures causes total failure 2024-07-16 23:34:15 -07:00
Koushik Dutta
e71f9b585c cloud: cors for manage.scrypted.app 2024-07-16 13:17:15 -07:00
Koushik Dutta
1effc45f18 sdk: add cloudHref to launcher 2024-07-16 11:27:00 -07:00
Koushik Dutta
2e5e5b7be0 common/core: automation/build fixes for new management site 2024-07-16 09:33:09 -07:00
Koushik Dutta
1df5cfefd0 working scheduler 2024-07-15 20:57:09 -07:00
Koushik Dutta
5d1e2663b8 rtp: fixup promise reject race condition 2024-07-15 14:26:25 -07:00
Koushik Dutta
59441c414b common: revert/fix deferred 2024-07-15 14:26:05 -07:00
Koushik Dutta
419d007445 rtsp: fix unhandled rejection if rtsp client is already destroyed 2024-07-15 13:53:55 -07:00
Koushik Dutta
90bca27bde http auth: improve status code handling 2024-07-15 11:56:39 -07:00
Koushik Dutta
0050624880 http digest auth: fix invalid status code not cleaning up http connections 2024-07-15 11:20:27 -07:00
Koushik Dutta
c4ea7938d1 core: wip automation settings 2024-07-14 23:02:12 -07:00
Koushik Dutta
b5d58455b6 core: transition to settings based automations 2024-07-14 20:11:23 -07:00
Koushik Dutta
82993df715 common: socket failure cleanups 2024-07-14 12:24:09 -07:00
Koushik Dutta
555a688c16 core: use provided nativeid in terminal service 2024-07-14 09:52:44 -07:00
Koushik Dutta
0241a5fb93 core: update sdk and fix build 2024-07-14 09:50:18 -07:00
Koushik Dutta
db7351e7d4 sdk: fix StreamService template args 2024-07-14 09:26:22 -07:00
Koushik Dutta
891e9792f8 sdk: uadd immediate setting flag 2024-07-14 09:17:17 -07:00
Koushik Dutta
97e7333415 core: dead import 2024-07-14 08:17:31 -07:00
Koushik Dutta
dc4dd07ced cloud: cleanup 2024-07-14 07:56:19 -07:00
Koushik Dutta
937f615c8c cloud: earlier unregistration fix for cloudflare 2024-07-14 07:55:38 -07:00
Koushik Dutta
7578cf092e amcrest: use VideoMotionInfo state to reset motion 2024-07-13 20:42:39 -07:00
Koushik Dutta
3041207177 zwave: update to latest zwave-js 2024-07-13 15:45:50 -07:00
Koushik Dutta
46d66122aa Merge branch 'main' of github.com:koush/scrypted 2024-07-12 18:05:58 -07:00
Koushik Dutta
d05e3a92f3 homekit: fix erroneous new subdevice reload 2024-07-12 18:05:53 -07:00
Brett Jia
4a4b077132 sdk: add generic params to StreamService + generate AsyncGenerator type hints in Python (#1527) 2024-07-12 08:08:28 -07:00
Koushik Dutta
cf5e010faf homekit: add codes to readme 2024-07-11 21:47:31 -07:00
Koushik Dutta
46616467f4 common: async queue wrapper for generator 2024-07-11 21:26:13 -07:00
Koushik Dutta
3dcb36adf9 Merge branch 'main' of github.com:koush/scrypted 2024-07-11 20:16:30 -07:00
Roman Sokolov
855940fb03 Hikvision Doorbell Plugin with inheritance (#1400)
* separate plugin

* added SIP "imitation". It almost works

* Refactoring

* Fixed some bugs. Added more UI

* Added descriptions and some fixes

* Stage before beta

* First beta done

* reset common settings

* Adding inheritance from Hikvision Camera plugin

* Added exposing tamper alert device

---------

Co-authored-by: Roman Sokolov <calm@adguard.com>
2024-07-11 16:56:07 -07:00
Brett Jia
1f25e1a308 core: allow specifying command via options (#1522) 2024-07-11 15:38:58 -07:00
Brett Jia
232298d7f4 server: fix python connectRPCObject sha256 (#1525) 2024-07-11 15:38:40 -07:00
Koushik Dutta
fa9b4f1a1c sdk: publish 2024-07-11 13:22:57 -07:00
Brett Jia
355c2719fd sdk: add TTY interface (#1526) 2024-07-11 13:22:18 -07:00
Brett Jia
dfb18ce882 server: fix crash fix on web-based connectRPCObject (#1524) 2024-07-11 09:56:31 -07:00
Koushik Dutta
07187d058b sdk: clippath setting support 2024-07-10 23:59:13 -07:00
Koushik Dutta
5060b5f8c7 homekit: show in scrypted settings 2024-07-10 21:08:37 -07:00
Koushik Dutta
50c628a25e Merge branch 'main' of github.com:koush/scrypted 2024-07-10 19:17:02 -07:00
Koushik Dutta
7bf4609d3d homekit: use html setting 2024-07-10 19:16:57 -07:00
Koushik Dutta
548a8eb321 sdk: update deps 2024-07-10 18:39:57 -07:00
Koushik Dutta
627f9e7a0a sdk: publish 2024-07-10 18:38:16 -07:00
Koushik Dutta
4faf85c988 sdk: update deps 2024-07-10 18:07:36 -07:00
Koushik Dutta
259c6434da Merge branch 'main' of github.com:koush/scrypted 2024-07-10 16:09:34 -07:00
Brett Jia
321d5b364f server: fix python systemManager.getDeviceByName (#1523) 2024-07-10 15:42:24 -07:00
Koushik Dutta
e56491ec27 common: refactor monaco hooks 2024-07-10 14:05:12 -07:00
Koushik Dutta
8fe5d1bace common: monaco typings 2024-07-10 13:17:05 -07:00
Koushik Dutta
4efa58ee8b sdk: add script setting type 2024-07-10 12:45:18 -07:00
Koushik Dutta
8249a5efa1 server: fixup engine.io typings 2024-07-10 11:58:29 -07:00
Koushik Dutta
08b0717407 rpc: move eval into separate file 2024-07-10 11:57:50 -07:00
Koushik Dutta
c277833332 sdk: publish 2024-07-10 11:39:05 -07:00
Koushik Dutta
37d9f2870d Merge branch 'main' of github.com:koush/scrypted 2024-07-10 11:38:15 -07:00
Koushik Dutta
cc71d1292b sdk: add support for day setting 2024-07-10 11:38:10 -07:00
slyoldfox
3ca6841ea2 Support v2 UI for sip and bticino plugins (#1521)
* Fix an undefined error that might occur when sip debug is off
Slight cleanup
Add support for v2 UI

* Decouple voicemail lock device from camera device and only add it for c300x models (c100x doesn't have voicemail)
Add support for v2 UI
Allow changing devaddr setting from UI

* Fix an undefined error that might occur when sip debug is off
Slight cleanup
Add support for v2 UI
2024-07-10 09:31:26 -07:00
Koushik Dutta
c81cdd0df1 server: update deps 2024-07-09 11:19:47 -07:00
Koushik Dutta
bd0cbe5e97 Revert "common: readd server dep"
This reverts commit fdd4eebd96.
2024-07-09 10:48:02 -07:00
Koushik Dutta
fdd4eebd96 common: readd server dep 2024-07-09 10:36:32 -07:00
Koushik Dutta
34eeaf5cce common: use relative import 2024-07-09 17:32:45 +00:00
Koushik Dutta
09c38e427a actions: Update build-sdk.yml 2024-07-09 10:28:07 -07:00
Koushik Dutta
fca2773282 remove wildcard export 2024-07-09 10:06:33 -07:00
Koushik Dutta
c138cc81c0 core: add core to new scrypted settings 2024-07-09 09:22:58 -07:00
Koushik Dutta
91be95e158 core: add support for system device creator 2024-07-09 09:03:53 -07:00
Koushik Dutta
e172b45047 cli: add support for session file path 2024-07-08 15:31:01 -07:00
Koushik Dutta
0a6c07551f cli: missing file 2024-07-08 15:26:56 -07:00
Koushik Dutta
fa33f850f7 cli: rtsp to mp4 converter 2024-07-08 15:25:21 -07:00
Koushik Dutta
605513d165 common: export sleep as relative file due to rollup quirks 2024-07-08 14:04:53 -07:00
Koushik Dutta
d635ab8662 common: bump ts 2024-07-08 14:01:27 -07:00
Koushik Dutta
4862705dcd common: fix sleep export 2024-07-08 13:51:05 -07:00
Koushik Dutta
4d471eb285 sdk/plugins/client/server: add new ScryptedDeviceCreator ui hooks 2024-07-08 09:43:30 -07:00
Koushik Dutta
470d315eaf client: build 2024-07-07 22:53:59 -07:00
Koushik Dutta
4e267e3de9 sdk: publish 2024-07-07 22:45:05 -07:00
Koushik Dutta
bd28cd1766 sdk: update with createdDevice string 2024-07-07 22:28:42 -07:00
Koushik Dutta
f5c324bd68 reolink: fallback if token exchange fails 2024-07-06 15:05:18 -07:00
Koushik Dutta
b7bf995303 mqtt: fix up device creation 2024-07-06 11:48:14 -07:00
Koushik Dutta
68516817aa cloud: fix tunnel registration failure hang 2024-07-06 00:08:43 -07:00
Koushik Dutta
9dc5f2a063 cloud: prefer cloudflared address if available 2024-07-05 17:57:08 -07:00
Koushik Dutta
d2564efe46 cloud: send custom domain header if its in use 2024-07-05 17:47:17 -07:00
Koushik Dutta
696e97914d common: formatting 2024-07-04 20:18:53 -07:00
Koushik Dutta
cafc5da8bf common: remove wildcard sleep export 2024-07-04 19:38:46 -07:00
Koushik Dutta
a24b6432c2 various: fixup strictness 2024-07-04 17:13:30 -07:00
Koushik Dutta
68668c1b91 Merge branch 'main' of github.com:koush/scrypted 2024-07-04 16:53:14 -07:00
Koushik Dutta
460441abd2 common: remove sleep 2024-07-04 16:53:09 -07:00
Koushik Dutta
3875afd002 client: publish 2024-07-04 16:52:47 -07:00
Koushik Dutta
f769c1fbec reolink: add more hw info 2024-07-04 14:50:15 -07:00
Koushik Dutta
644df95f21 reolink: add more hw info 2024-07-04 14:49:05 -07:00
Koushik Dutta
95f1e618f9 unifi-protect: ips 2024-07-04 14:44:15 -07:00
Koushik Dutta
03e6cf1070 Merge branch 'main' of github.com:koush/scrypted 2024-07-02 12:39:00 -07:00
Koushik Dutta
f01a207166 common: export sleep from server 2024-07-02 12:38:55 -07:00
Long Zheng
1795996825 windows: Fix plugin NPM dependencies failing to install on Windows with path containing space (#1517) 2024-06-30 23:15:32 -07:00
Koushik Dutta
375f7bcc09 Merge branch 'main' of github.com:koush/scrypted 2024-06-29 19:29:25 -07:00
Koushik Dutta
76f10ced5f ha: verup 2024-06-29 19:29:21 -07:00
Koushik Dutta
37c791f147 predict: update opencv dep, make required 2024-06-29 15:22:02 -07:00
Koushik Dutta
9a8034eb4c h264: fix bug when stapa packet overflows packetizing a large p frame 2024-06-28 20:00:50 -07:00
Koushik Dutta
ff70ed301e webrtc/homekit: publish mtu changes 2024-06-28 13:14:46 -07:00
Koushik Dutta
3f66594821 reolink: use username and password if it works, fallback to token otherwise 2024-06-28 12:32:14 -07:00
Koushik Dutta
f2cd0218fd reolink: switch to mainEncType marker 2024-06-28 11:12:01 -07:00
Koushik Dutta
028d601674 reolink: automatically remove nonfunctional streams using opaque getAbility api results lol 2024-06-28 10:37:58 -07:00
Koushik Dutta
e06d012875 Revert "Breaks snapshot on doorbell. Not sure why."
This reverts commit 91fbc2fdf8.
2024-06-28 10:35:18 -07:00
Koushik Dutta
5995400414 reolink: log startup error 2024-06-28 09:53:34 -07:00
Koushik Dutta
91fbc2fdf8 Breaks snapshot on doorbell. Not sure why.
Revert "reolink: use Login json api to get around URL escaping limitations with some firmware (#1509)"

This reverts commit fc93a85e21.
2024-06-28 09:42:59 -07:00
Koushik Dutta
6b00324c74 webrtc/homekit: reduce mtu, prep for adaptive bitrate 2024-06-28 09:37:53 -07:00
Koushik Dutta
1369197a11 sdk: revert mtu callback 2024-06-28 09:32:11 -07:00
Koushik Dutta
a30580f3b8 openvino: lock to f16. todo remove multiple precisions. 2024-06-28 09:21:47 -07:00
George Talusan
fc93a85e21 reolink: use Login json api to get around URL escaping limitations with some firmware (#1509) 2024-06-27 21:54:04 -07:00
jstef16
5351d869d4 homekit: fix window covering target position binding (#1512)
Co-authored-by: Jordan Steffan <jordansteffan@Jordans-Mini.localdomain>
2024-06-27 21:50:55 -07:00
Koushik Dutta
a61d9af25c sdk: add hook to set mtu and listen for mtu change requests. 2024-06-27 15:45:36 -07:00
Koushik Dutta
2111413704 reolink: remove debug code 2024-06-27 12:56:54 -07:00
Koushik Dutta
a2781f9af2 reolink/common: siren fixes 2024-06-27 10:51:16 -07:00
Koushik Dutta
09eeae3802 reolink: unhide the doorbell checkbox 2024-06-27 10:24:38 -07:00
Koushik Dutta
0408b7e23d reolink: fix broken doorbell. 2024-06-27 10:15:49 -07:00
Koushik Dutta
ea606de22f postrelease 2024-06-26 09:43:48 -07:00
Koushik Dutta
9fbff43120 Merge branch 'main' of github.com:koush/scrypted 2024-06-25 22:23:08 -07:00
Koushik Dutta
bc358af5fa postrelease 2024-06-25 22:23:03 -07:00
George Talusan
4452568058 reolink: fix deviceprovider for cameras with siren (#1508) 2024-06-25 22:15:23 -07:00
512 changed files with 25766 additions and 50908 deletions

View File

@@ -7,7 +7,7 @@ on:
pull_request:
paths: ["sdk/**"]
workflow_dispatch:
jobs:
build:
name: Build
@@ -15,11 +15,11 @@ jobs:
defaults:
run:
working-directory: ./sdk
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 18
node-version: 22.4.1
- run: npm ci
- run: npm run build

44
.github/workflows/static-sites.yml vendored Normal file
View File

@@ -0,0 +1,44 @@
# Simple workflow for deploying static content to GitHub Pages
name: Deploy static content to Pages
on:
# Runs on pushes targeting the default branch
push:
branches: ["main"]
paths: ["sites/static/**", ".github/workflows/static-sites.yml"]
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages
permissions:
contents: read
pages: write
id-token: write
# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued.
# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete.
concurrency:
group: "pages"
cancel-in-progress: false
jobs:
# Single deploy job since we're just deploying
deploy:
environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Setup Pages
uses: actions/configure-pages@v5
- name: Upload artifact
uses: actions/upload-pages-artifact@v3
with:
# Upload entire repository
path: './sites/static'
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@v4

9
.gitmodules vendored
View File

@@ -1,9 +1,6 @@
[submodule "plugins/unifi-protect/src/unifi-protect"]
path = external/unifi-protect
url = ../../koush/unifi-protect.git
[submodule "plugins/myq/src/myq"]
path = plugins/myq/src/myq
url = ../../koush/myq.git
[submodule "external/ring-client-api"]
path = external/ring-client-api
url = ../../koush/ring
@@ -14,9 +11,6 @@
[submodule "external/werift"]
path = external/werift
url = ../../koush/werift-webrtc
[submodule "plugins/zwave/file-stream-rotator"]
path = plugins/zwave/file-stream-rotator
url = ../../koush/file-stream-rotator.git
[submodule "sdk/developer.scrypted.app"]
path = sdk/developer.scrypted.app
url = ../../koush/developer.scrypted.app
@@ -29,6 +23,3 @@
[submodule "plugins/wyze/docker-wyze-bridge"]
path = plugins/wyze/docker-wyze-bridge
url = ../../koush/docker-wyze-bridge.git
[submodule "plugins/onvif/onvif"]
path = plugins/onvif/onvif
url = ../../koush/onvif.git

108
common/package-lock.json generated
View File

@@ -10,12 +10,12 @@
"license": "ISC",
"dependencies": {
"@scrypted/sdk": "file:../sdk",
"@scrypted/server": "file:../server",
"http-auth-utils": "^5.0.1",
"typescript": "^5.3.3"
"typescript": "^5.5.3"
},
"devDependencies": {
"@types/node": "^20.11.0",
"monaco-editor": "^0.50.0",
"ts-node": "^10.9.2"
}
},
@@ -74,7 +74,7 @@
},
"../sdk": {
"name": "@scrypted/sdk",
"version": "0.3.29",
"version": "0.3.45",
"license": "ISC",
"dependencies": {
"@babel/preset-typescript": "^7.18.6",
@@ -111,39 +111,40 @@
},
"../server": {
"name": "@scrypted/server",
"version": "0.106.0",
"version": "0.115.0",
"extraneous": true,
"hasInstallScript": true,
"license": "ISC",
"dependencies": {
"@mapbox/node-pre-gyp": "^1.0.11",
"@scrypted/ffmpeg-static": "^6.1.0-build1",
"@scrypted/node-pty": "^1.0.10",
"@scrypted/types": "^0.3.28",
"adm-zip": "^0.5.12",
"@scrypted/node-pty": "^1.0.18",
"@scrypted/types": "^0.3.33",
"adm-zip": "^0.5.14",
"body-parser": "^1.20.2",
"cookie-parser": "^1.4.6",
"dotenv": "^16.4.5",
"engine.io": "^6.5.4",
"engine.io": "^6.6.0",
"express": "^4.19.2",
"follow-redirects": "^1.15.6",
"http-auth": "^4.2.0",
"ip": "^2.0.1",
"level": "^8.0.1",
"lodash": "^4.17.21",
"nan": "^2.19.0",
"nan": "^2.20.0",
"node-dijkstra": "^2.5.0",
"node-forge": "^1.3.1",
"node-gyp": "^10.1.0",
"py": "npm:@bjia56/portable-python@^0.1.31",
"py": "npm:@bjia56/portable-python@^0.1.54",
"router": "^1.3.8",
"semver": "^7.6.2",
"sharp": "^0.33.3",
"sharp": "^0.33.4",
"source-map-support": "^0.5.21",
"tar": "^7.1.0",
"tslib": "^2.6.2",
"typescript": "^5.4.5",
"tar": "^7.4.0",
"tslib": "^2.6.3",
"typescript": "^5.5.3",
"whatwg-mimetype": "^4.0.0",
"ws": "^8.17.0"
"ws": "^8.18.0"
},
"bin": {
"scrypted-serve": "bin/scrypted-serve"
@@ -155,7 +156,7 @@
"@types/follow-redirects": "^1.14.4",
"@types/http-auth": "^4.1.4",
"@types/ip": "^1.1.3",
"@types/lodash": "^4.17.1",
"@types/lodash": "^4.17.6",
"@types/node-dijkstra": "^2.5.6",
"@types/node-forge": "^1.3.11",
"@types/semver": "^7.5.8",
@@ -205,10 +206,6 @@
"resolved": "../sdk",
"link": true
},
"node_modules/@scrypted/server": {
"resolved": "../server",
"link": true
},
"node_modules/@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
@@ -301,6 +298,12 @@
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/monaco-editor": {
"version": "0.50.0",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.50.0.tgz",
"integrity": "sha512-8CclLCmrRRh+sul7C08BmPBP3P8wVWfBHomsTcndxg5NRCEPfu/mc2AGU8k37ajjDVXcXFc12ORAMUkmk+lkFA==",
"dev": true
},
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
@@ -345,9 +348,9 @@
}
},
"node_modules/typescript": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==",
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
"integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ==",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
@@ -442,53 +445,6 @@
"webpack-bundle-analyzer": "^4.5.0"
}
},
"@scrypted/server": {
"version": "file:../server",
"requires": {
"@mapbox/node-pre-gyp": "^1.0.11",
"@scrypted/ffmpeg-static": "^6.1.0-build1",
"@scrypted/node-pty": "^1.0.10",
"@scrypted/types": "^0.3.28",
"@types/adm-zip": "^0.5.5",
"@types/cookie-parser": "^1.4.7",
"@types/express": "^4.17.21",
"@types/follow-redirects": "^1.14.4",
"@types/http-auth": "^4.1.4",
"@types/ip": "^1.1.3",
"@types/lodash": "^4.17.1",
"@types/node-dijkstra": "^2.5.6",
"@types/node-forge": "^1.3.11",
"@types/semver": "^7.5.8",
"@types/source-map-support": "^0.5.10",
"@types/whatwg-mimetype": "^3.0.2",
"@types/ws": "^8.5.10",
"adm-zip": "^0.5.12",
"body-parser": "^1.20.2",
"cookie-parser": "^1.4.6",
"dotenv": "^16.4.5",
"engine.io": "^6.5.4",
"express": "^4.19.2",
"follow-redirects": "^1.15.6",
"http-auth": "^4.2.0",
"ip": "^2.0.1",
"level": "^8.0.1",
"lodash": "^4.17.21",
"nan": "^2.19.0",
"node-dijkstra": "^2.5.0",
"node-forge": "^1.3.1",
"node-gyp": "^10.1.0",
"py": "npm:@bjia56/portable-python@^0.1.31",
"router": "^1.3.8",
"semver": "^7.6.2",
"sharp": "^0.33.3",
"source-map-support": "^0.5.21",
"tar": "^7.1.0",
"tslib": "^2.6.2",
"typescript": "^5.4.5",
"whatwg-mimetype": "^4.0.0",
"ws": "^8.17.0"
}
},
"@tsconfig/node10": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz",
@@ -566,6 +522,12 @@
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"monaco-editor": {
"version": "0.50.0",
"resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.50.0.tgz",
"integrity": "sha512-8CclLCmrRRh+sul7C08BmPBP3P8wVWfBHomsTcndxg5NRCEPfu/mc2AGU8k37ajjDVXcXFc12ORAMUkmk+lkFA==",
"dev": true
},
"ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
@@ -588,9 +550,9 @@
}
},
"typescript": {
"version": "5.3.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz",
"integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw=="
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.3.tgz",
"integrity": "sha512-/hreyEujaB0w76zKo6717l3L0o/qEUtRgdvUBvlkhoWeOVMjMuHNHk0BRBzikzuGDqNmPQbg5ifMEqsHLiIUcQ=="
},
"undici-types": {
"version": "5.26.5",

View File

@@ -12,12 +12,12 @@
"license": "ISC",
"dependencies": {
"@scrypted/sdk": "file:../sdk",
"@scrypted/server": "file:../server",
"http-auth-utils": "^5.0.1",
"typescript": "^5.3.3"
"typescript": "^5.5.3"
},
"devDependencies": {
"@types/node": "^20.11.0",
"monaco-editor": "^0.50.0",
"ts-node": "^10.9.2"
}
}

View File

@@ -40,7 +40,7 @@ export function createAsyncQueue<T>() {
return false;
if (waiting.length) {
const deferred = waiting.shift();
const deferred = waiting.shift()!;
dequeued?.resolve();
deferred.resolve(item);
return true;
@@ -66,7 +66,7 @@ export function createAsyncQueue<T>() {
dequeued?.reject(new Error('abort'));
};
dequeued.promise.catch(() => {}).finally(() => signal.removeEventListener('abort', h));
dequeued?.promise.catch(() => {}).finally(() => signal.removeEventListener('abort', h));
signal.addEventListener('abort', h);
return true;
@@ -79,7 +79,7 @@ export function createAsyncQueue<T>() {
ended = e || new EndError();
endDeferred.resolve();
while (waiting.length) {
waiting.shift().reject(ended);
waiting.shift()!.reject(ended);
}
return true;
}
@@ -94,7 +94,7 @@ export function createAsyncQueue<T>() {
}
catch (e) {
// the yield above may raise an error, and the queue should be ended.
end(e);
end(e as Error);
if (e instanceof EndError)
return;
throw e;
@@ -155,6 +155,23 @@ export function createAsyncQueue<T>() {
}
}
export function createAsyncQueueFromGenerator<T>(generator: AsyncGenerator<T>) {
const q = createAsyncQueue<T>();
(async() => {
try {
for await (const i of generator) {
q.submit(i);
}
}
catch (e) {
q.end(e as Error);
}
q.end();
})();
return q;
}
// async function testSlowEnqueue() {
// const asyncQueue = createAsyncQueue<number>();

View File

@@ -0,0 +1,209 @@
import sdk, { AudioStreamOptions, MediaStreamConfiguration, MediaStreamDestination, MediaStreamOptions, ScryptedDeviceBase, Setting } from "@scrypted/sdk";
export const automaticallyConfigureSettings: Setting = {
key: 'autoconfigure',
title: 'Automatically Configure Settings',
description: 'Automatically configure and valdiate the camera codecs and other settings for optimal Scrypted performance. Some settings will require manual configuration via the camera web admin.',
type: 'boolean',
value: true,
};
export const onvifAutoConfigureSettings: Setting = {
key: 'onvif-autoconfigure',
type: 'html',
value: 'ONVIF autoconfiguration will configure the camera codecs. <b>The camera motion sensor must still be <a target="_blank" href="https://docs.scrypted.app/camera-preparation.html#motion-sensor-setup">configured manually</a>.</b>',
};
const MEGABIT = 1024 * 1000;
function getBitrateForResolution(resolution: number) {
if (resolution >= 3840 * 2160)
return 8 * MEGABIT;
if (resolution >= 2688 * 1520)
return 3 * MEGABIT;
if (resolution >= 1920 * 1080)
return 2 * MEGABIT;
if (resolution >= 1280 * 720)
return MEGABIT;
if (resolution >= 640 * 480)
return MEGABIT / 2;
return MEGABIT / 4;
}
export async function checkPluginNeedsAutoConfigure(plugin: ScryptedDeviceBase, extraDevices = 0) {
if (plugin.storage.getItem('autoconfigure') === 'true')
return;
plugin.storage.setItem('autoconfigure', 'true');
if (sdk.deviceManager.getNativeIds().length <= 1 + extraDevices)
return;
plugin.log.a(`${plugin.name} now has support for automatic camera configuration for optimal performance. Cameras can be autoconfigured in their respective settings.`);
}
export async function autoconfigureCodecs(
getCodecs: () => Promise<MediaStreamOptions[]>,
configureCodecs: (options: MediaStreamOptions) => Promise<MediaStreamConfiguration>,
audioOptions?: AudioStreamOptions,
) {
audioOptions ||= {
codec: 'pcm_mulaw',
bitrate: 64000,
sampleRate: 8000,
};
const codecs = await getCodecs();
const configurable: MediaStreamConfiguration[] = [];
for (const codec of codecs) {
const config = await configureCodecs({
id: codec.id,
});
configurable.push(config);
}
const used: MediaStreamConfiguration[] = [];
for (const _ of ['local', 'remote', 'low-resolution'] as MediaStreamDestination[]) {
// find stream with the highest configurable resolution.
let highest: [MediaStreamConfiguration, number] = [undefined, 0];
for (const codec of configurable) {
if (used.includes(codec))
continue;
for (const resolution of codec.video.resolutions) {
if (resolution[0] * resolution[1] > highest[1]) {
highest = [codec, resolution[0] * resolution[1]];
}
}
}
const config = highest[0];
if (!config)
break;
used.push(config);
}
const findResolutionTarget = (config: MediaStreamConfiguration, width: number, height: number) => {
let diff = 999999999;
let ret: [number, number];
const targetArea = width * height;
for (const res of config.video.resolutions) {
const actualArea = res[0] * res[1];
const diffArea = Math.abs(targetArea - actualArea);
if (diffArea < diff) {
diff = diffArea;
ret = res;
}
}
return ret;
}
// find the highest resolution
const l = used[0];
const resolution = findResolutionTarget(l, 8192, 8192);
// get the fps of 20 or highest available
let fps = Math.min(20, Math.max(...l.video.fpsRange));
let errors = '';
const logConfigureCodecs = async (config: MediaStreamConfiguration) => {
try {
await configureCodecs(config);
}
catch (e) {
errors += e;
}
}
await logConfigureCodecs({
id: l.id,
video: {
width: resolution[0],
height: resolution[1],
bitrateControl: 'variable',
codec: 'h264',
bitrate: getBitrateForResolution(resolution[0] * resolution[1]),
fps,
keyframeInterval: fps * 4,
quality: 5,
profile: 'main',
},
audio: audioOptions,
});
if (used.length === 3) {
// find remote and low
const r = used[1];
const l = used[2];
const rResolution = findResolutionTarget(r, 1280, 720);
const lResolution = findResolutionTarget(l, 640, 360);
fps = Math.min(20, Math.max(...r.video.fpsRange));
await logConfigureCodecs({
id: r.id,
video: {
width: rResolution[0],
height: rResolution[1],
bitrateControl: 'variable',
codec: 'h264',
bitrate: 1 * MEGABIT,
fps,
keyframeInterval: fps * 4,
quality: 5,
profile: 'main',
},
audio: audioOptions,
});
fps = Math.min(20, Math.max(...l.video.fpsRange));
await logConfigureCodecs({
id: l.id,
video: {
width: lResolution[0],
height: lResolution[1],
bitrateControl: 'variable',
codec: 'h264',
bitrate: MEGABIT / 2,
fps,
keyframeInterval: fps * 4,
quality: 5,
profile: 'main',
},
audio: audioOptions,
});
}
else if (used.length == 2) {
let target: [number, number];
if (resolution[0] * resolution[1] > 1920 * 1080)
target = [1280, 720];
else
target = [640, 360];
const rResolution = findResolutionTarget(used[1], target[0], target[1]);
const fps = Math.min(20, Math.max(...used[1].video.fpsRange));
await logConfigureCodecs({
id: used[1].id,
video: {
width: rResolution[0],
height: rResolution[1],
bitrateControl: 'variable',
codec: 'h264',
bitrate: getBitrateForResolution(rResolution[0] * rResolution[1]),
fps,
keyframeInterval: fps * 4,
quality: 5,
profile: 'main',
},
audio: audioOptions,
});
}
else if (used.length === 1) {
// no nop
}
if (errors)
throw new Error(errors);
}

View File

@@ -41,11 +41,15 @@ export abstract class AutoenableMixinProvider extends ScryptedDeviceBase {
return true;
}
checkHasEnabledMixin(device: ScryptedDevice) {
return this.hasEnabledMixin[device.id] === this.autoIncludeToken;
}
async maybeEnableMixin(device: ScryptedDevice) {
if (!device || device.mixins?.includes(this.id))
return;
if (this.hasEnabledMixin[device.id] === this.autoIncludeToken)
if (this.checkHasEnabledMixin(device))
return;
const match = await this.canMixin(device.type, device.interfaces);

View File

@@ -1,17 +0,0 @@
export class Deferred<T> {
finished = false;
resolve!: (value: T|PromiseLike<T>) => this;
reject!: (error: Error) => this;
promise: Promise<T> = new Promise((resolve, reject) => {
this.resolve = v => {
this.finished = true;
resolve(v);
return this;
};
this.reject = e => {
this.finished = true;
reject(e);
return this;
};
});
}

1
common/src/deferred.ts Symbolic link
View File

@@ -0,0 +1 @@
../../server/src/deferred.ts

View File

@@ -0,0 +1,96 @@
import type * as monacoEditor from 'monaco-editor';
export interface StandardLibs {
'@types/node/globals.d.ts': string,
'@types/node/buffer.d.ts': string,
'@types/node/process.d.ts': string,
'@types/node/events.d.ts': string,
'@types/node/stream.d.ts': string,
'@types/node/fs.d.ts': string,
'@types/node/net.d.ts': string,
'@types/node/child_process.d.ts': string,
}
export interface ScryptedLibs {
'@types/sdk/settings-mixin.d.ts': string,
'@types/sdk/storage-settings.d.ts': string,
'@types/sdk/types.d.ts': string,
'@types/sdk/index.d.ts': string,
}
export function createMonacoEvalDefaultsWithLibs(standardLibs: StandardLibs, scryptedLibs: ScryptedLibs, extraLibs: { [lib: string]: string }) {
// const libs = Object.assign(scryptedLibs, extraLibs);
function monacoEvalDefaultsFunction(monaco: typeof monacoEditor, standardLibs: StandardLibs, scryptedLibs: ScryptedLibs, extraLibs: { [lib: string]: string }) {
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions(
Object.assign(
{},
monaco.languages.typescript.typescriptDefaults.getDiagnosticsOptions(),
{
diagnosticCodesToIgnore: [1108, 1375, 1378],
}
)
);
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
Object.assign(
{},
monaco.languages.typescript.typescriptDefaults.getCompilerOptions(),
{
moduleResolution:
monaco.languages.typescript.ModuleResolutionKind.NodeJs,
}
)
);
const libs: any = {
...scryptedLibs,
...extraLibs,
};
const catLibs = Object.values(libs).join('\n');
const catlibsNoExport = Object.keys(libs)
.map(lib => libs[lib]).map(lib =>
lib.toString().replace(/export /g, '').replace(/import.*?/g, ''))
.join('\n');
monaco.languages.typescript.typescriptDefaults.addExtraLib(`
${catLibs}
declare global {
${catlibsNoExport}
const log: Logger;
const deviceManager: DeviceManager;
const endpointManager: EndpointManager;
const mediaManager: MediaManager;
const systemManager: SystemManager;
const eventSource: ScryptedDevice;
const eventDetails: EventDetails;
const eventData: any;
}
`,
"node_modules/@types/scrypted__sdk/types/index.d.ts"
);
for (const lib of Object.keys(standardLibs)) {
monaco.languages.typescript.typescriptDefaults.addExtraLib(
standardLibs[lib as keyof StandardLibs],
lib,
);
}
}
return `(function() {
const standardLibs = ${JSON.stringify(standardLibs)};
const scryptedLibs = ${JSON.stringify(scryptedLibs)};
const extraLibs = ${JSON.stringify(extraLibs)};
return (monaco) => {
(${monacoEvalDefaultsFunction})(monaco, standardLibs, scryptedLibs, extraLibs);
}
})();
`;
}

View File

@@ -1,3 +1,5 @@
import type { ScryptedDeviceBase } from "@scrypted/sdk";
export interface ScriptDevice {
/**
* @deprecated Use the default export to specify the device handler.
@@ -6,3 +8,5 @@ export interface ScriptDevice {
handle<T>(handler?: T & object): void;
handleTypes(...interfaces: string[]): void;
}
export declare const device: ScryptedDeviceBase & ScriptDevice;

View File

@@ -1,9 +1,10 @@
import sdk, { MixinDeviceBase, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, ScryptedInterfaceDescriptors, ScryptedMimeTypes } from "@scrypted/sdk";
import { StorageSettings } from "@scrypted/sdk/storage-settings";
import sdk, { LockState, MixinDeviceBase, PanTiltZoomMovement, ScryptedDeviceBase, ScryptedDeviceType, ScryptedInterface, ScryptedInterfaceDescriptors, ScryptedMimeTypes } from "@scrypted/sdk";
import { SettingsMixinDeviceBase } from "@scrypted/sdk/settings-mixin";
import { StorageSettings } from "@scrypted/sdk/storage-settings";
import fs from 'fs';
import type { TranspileOptions } from "typescript";
import vm from "vm";
import { createMonacoEvalDefaultsWithLibs, ScryptedLibs, StandardLibs } from "./monaco-libs";
import { ScriptDevice } from "./monaco/script-device";
const { systemManager, deviceManager, mediaManager, endpointManager } = sdk;
@@ -28,22 +29,18 @@ export function readFileAsString(f: string) {
return fs.readFileSync(f).toString();;
}
function getTypeDefs() {
const settingsMixinDefs = readFileAsString('@types/sdk/settings-mixin.d.ts');
const storageSettingsDefs = readFileAsString('@types/sdk/storage-settings.d.ts');
const scryptedTypesDefs = readFileAsString('@types/sdk/types.d.ts');
const scryptedIndexDefs = readFileAsString('@types/sdk/index.d.ts');
function getScryptedLibs(): ScryptedLibs {
return {
settingsMixinDefs,
storageSettingsDefs,
scryptedIndexDefs,
scryptedTypesDefs,
};
"@types/sdk/index.d.ts": readFileAsString('@types/sdk/index.d.ts'),
"@types/sdk/settings-mixin.d.ts": readFileAsString('@types/sdk/settings-mixin.d.ts'),
"@types/sdk/storage-settings.d.ts": readFileAsString('@types/sdk/storage-settings.d.ts'),
"@types/sdk/types.d.ts": readFileAsString('@types/sdk/types.d.ts'),
}
}
export async function scryptedEval(device: ScryptedDeviceBase, script: string, extraLibs: { [lib: string]: string }, params: { [name: string]: any }) {
const libs = Object.assign({
types: getTypeDefs().scryptedTypesDefs,
types: getScryptedLibs()['@types/sdk/types.d.ts'],
}, extraLibs);
const allScripts = Object.values(libs).join('\n').toString() + script;
let compiled: string;
@@ -79,6 +76,7 @@ export async function scryptedEval(device: ScryptedDeviceBase, script: string, e
localStorage: device.storage,
device,
exports: {} as any,
PanTiltZoomMovement,
SettingsMixinDeviceBase,
ScryptedMimeTypes,
ScryptedInterface,
@@ -117,102 +115,18 @@ export async function scryptedEval(device: ScryptedDeviceBase, script: string, e
}
export function createMonacoEvalDefaults(extraLibs: { [lib: string]: string }) {
const safeLibs: any = {};
const standardlibs: StandardLibs = {
"@types/node/globals.d.ts": readFileAsString('@types/node/globals.d.ts'),
"@types/node/buffer.d.ts": readFileAsString('@types/node/buffer.d.ts'),
"@types/node/process.d.ts": readFileAsString('@types/node/process.d.ts'),
"@types/node/events.d.ts": readFileAsString('@types/node/events.d.ts'),
"@types/node/stream.d.ts": readFileAsString('@types/node/stream.d.ts'),
"@types/node/fs.d.ts": readFileAsString('@types/node/fs.d.ts'),
"@types/node/net.d.ts": readFileAsString('@types/node/net.d.ts'),
"@types/node/child_process.d.ts": readFileAsString('@types/node/child_process.d.ts'),
};
for (const safeLib of [
'@types/node/globals.d.ts',
'@types/node/buffer.d.ts',
'@types/node/process.d.ts',
'@types/node/events.d.ts',
'@types/node/stream.d.ts',
'@types/node/fs.d.ts',
'@types/node/net.d.ts',
'@types/node/child_process.d.ts',
]) {
safeLibs[`node_modules/${safeLib}`] = readFileAsString(safeLib)
}
const libs = Object.assign(getTypeDefs(), extraLibs);
function monacoEvalDefaultsFunction(monaco: any, safeLibs: any, libs: any) {
monaco.languages.typescript.typescriptDefaults.setDiagnosticsOptions(
Object.assign(
{},
monaco.languages.typescript.typescriptDefaults.getDiagnosticsOptions(),
{
diagnosticCodesToIgnore: [1108, 1375, 1378],
}
)
);
monaco.languages.typescript.typescriptDefaults.setCompilerOptions(
Object.assign(
{},
monaco.languages.typescript.typescriptDefaults.getCompilerOptions(),
{
moduleResolution:
monaco.languages.typescript.ModuleResolutionKind.NodeJs,
}
)
);
const catLibs = Object.values(libs).join('\n');
const catlibsNoExport = Object.keys(libs).filter(lib => lib !== 'sdk')
.map(lib => libs[lib]).map(lib =>
lib.toString().replace(/export /g, '').replace(/import.*?/g, ''))
.join('\n');
monaco.languages.typescript.typescriptDefaults.addExtraLib(`
${catLibs}
declare global {
${catlibsNoExport}
const log: Logger;
const deviceManager: DeviceManager;
const endpointManager: EndpointManager;
const mediaManager: MediaManager;
const systemManager: SystemManager;
const mqtt: MqttClient;
const device: ScryptedDeviceBase & { pathname : string };
}
`,
"node_modules/@types/scrypted__sdk/types/index.d.ts"
);
monaco.languages.typescript.typescriptDefaults.addExtraLib(
libs['settingsMixin'],
"node_modules/@types/scrypted__sdk/settings-mixin.d.ts"
);
monaco.languages.typescript.typescriptDefaults.addExtraLib(
libs['storageSettings'],
"node_modules/@types/scrypted__sdk/storage-settings.d.ts"
);
monaco.languages.typescript.typescriptDefaults.addExtraLib(
libs['sdk'],
"node_modules/@types/scrypted__sdk/index.d.ts"
);
for (const lib of Object.keys(safeLibs)) {
monaco.languages.typescript.typescriptDefaults.addExtraLib(
safeLibs[lib],
lib,
);
}
}
return `(function() {
const safeLibs = ${JSON.stringify(safeLibs)};
const libs = ${JSON.stringify(libs)};
return (monaco) => {
(${monacoEvalDefaultsFunction})(monaco, safeLibs, libs);
}
})();
`;
return createMonacoEvalDefaultsWithLibs(standardlibs, getScryptedLibs(), extraLibs);
}
export interface ScriptDeviceImpl extends ScriptDevice {

View File

@@ -79,4 +79,4 @@ export async function bind(server: dgram.Socket, port: number) {
}
}
export { ListenZeroSingleClientTimeoutError, listenZero, listenZeroSingleClient } from "@scrypted/server/src/listen-zero";
export { ListenZeroSingleClientTimeoutError, listenZero, listenZeroSingleClient } from "../../server/src/listen-zero";

View File

@@ -1 +1 @@
export * from '@scrypted/server/src/media-helpers';
export { safeKillFFmpeg, ffmpegLogInitialOutput, safePrintFFmpegArguments } from '../../server/src/media-helpers';

View File

@@ -54,18 +54,18 @@ export async function read16BELengthLoop(readable: Readable, options: {
readable.on('readable', read);
await once(readable, 'end');
throw new Error('stream ended');
throw new StreamEndError('read16BELengthLoop');
}
export class StreamEndError extends Error {
constructor() {
super('stream ended');
constructor(where: string) {
super(`stream ended: ${where}`);
}
}
export async function readLength(readable: Readable, length: number): Promise<Buffer> {
if (readable.readableEnded || readable.destroyed)
throw new StreamEndError();
throw new StreamEndError('readLength start');
if (!length) {
return Buffer.alloc(0);
@@ -88,12 +88,12 @@ export async function readLength(readable: Readable, length: number): Promise<Bu
}
if (readable.readableEnded || readable.destroyed)
reject(new Error("stream ended during read"));
reject(new StreamEndError('readLength readable'));
};
const e = () => {
cleanup();
reject(new StreamEndError())
reject(new StreamEndError('readLength end'));
};
const cleanup = () => {

View File

@@ -1,5 +1,5 @@
import { RpcPeer } from "@scrypted/server/src/rpc";
import { createRpcSerializer } from "@scrypted/server/src/rpc-serializer";
import { RpcPeer } from "../../server/src/rpc";
import { createRpcSerializer } from "../../server/src/rpc-serializer";
import type { RTCSignalingSession } from "@scrypted/sdk";
export async function createBrowserSignalingSession(ws: WebSocket, localName: string, remoteName: string) {

View File

@@ -41,15 +41,15 @@ export function isPeerConnectionClosed(pc: RTCPeerConnection) {
|| pc.iceConnectionState === 'closed';
}
function silence() {
let ctx = new AudioContext(), oscillator = ctx.createOscillator();
const dest = ctx.createMediaStreamDestination();
oscillator.connect(dest);
oscillator.start();
const ret = dest.stream.getAudioTracks()[0];
ret.enabled = false;
return ret;
}
// function silence() {
// let ctx = new AudioContext(), oscillator = ctx.createOscillator();
// const dest = ctx.createMediaStreamDestination();
// oscillator.connect(dest);
// oscillator.start();
// const ret = dest.stream.getAudioTracks()[0];
// ret.enabled = false;
// return ret;
// }
function createOptions() {
const options: RTCSignalingOptions = {

View File

@@ -506,7 +506,7 @@ export class RtspClient extends RtspBase {
}
}
catch (e) {
this.client.destroy(e);
this.client.destroy(e as Error);
throw e;
}
}
@@ -572,7 +572,8 @@ export class RtspClient extends RtspBase {
}
}
catch (e) {
deferred.reject(e);
if (!deferred.finished)
deferred.reject(e as Error);
this.client.destroy();
}
};
@@ -725,7 +726,10 @@ export class RtspClient extends RtspBase {
Accept: 'application/sdp',
});
this.contentBase = response.headers['content-base'] || response.headers['content-location'];;
this.contentBase = response.headers['content-base'] || response.headers['content-location'];
// content base may be a relative path? seems odd.
if (this.contentBase)
this.contentBase = new URL(this.contentBase, this.url).toString();
return response;
}
@@ -1123,7 +1127,7 @@ export class RtspServer {
}
export async function listenSingleRtspClient<T extends RtspServer>(options?: {
hostname?: string,
hostname: string,
pathToken?: string,
createServer?(duplex: Duplex): T,
}) {

View File

@@ -227,6 +227,10 @@ export function parseRtpMap(mline: ReturnType<typeof parseMLine>, rtpmap: string
codec = 'pcm_alaw';
ffmpegEncoder = 'pcm_alaw';
}
else if (mline.payloadTypes?.includes(14)) {
codec = 'mp3';
ffmpegEncoder = 'mp3';
}
else {
// ffmpeg seems to omit the rtpmap type for pcm alaw when creating sdp?
// is this the default?

View File

@@ -1 +1 @@
export * from "@scrypted/server/src/sleep"
export { sleep } from "../../server/src/sleep";

View File

@@ -1,19 +1,15 @@
import sdk, { PluginFork } from '@scrypted/sdk';
import worker_threads from 'worker_threads';
import sdk, { ForkOptions, PluginFork } from '@scrypted/sdk';
import { createAsyncQueue } from './async-queue';
import os from 'os';
export type Zygote<T> = () => PluginFork<T>;
export function createZygote<T>(): Zygote<T> {
if (!worker_threads.isMainThread)
return;
let zygote = sdk.fork<T>();
export function createZygote<T>(options?: ForkOptions): Zygote<T> {
let zygote = sdk.fork<T>(options);
function* next() {
while (true) {
const cur = zygote;
zygote = sdk.fork<T>();
zygote = sdk.fork<T>(options);
yield cur;
}
}

View File

@@ -1,6 +1,6 @@
{
"compilerOptions": {
"module": "Node16",
"module": "commonjs",
"moduleResolution": "Node16",
"target": "esnext",
"noImplicitAny": true,

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 17 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 75 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 91 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.6 KiB

View File

@@ -1 +0,0 @@
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-cpu"><rect x="4" y="4" width="16" height="16" rx="2" ry="2"></rect><rect x="9" y="9" width="6" height="6"></rect><line x1="9" y1="1" x2="9" y2="4"></line><line x1="15" y1="1" x2="15" y2="4"></line><line x1="9" y1="20" x2="9" y2="23"></line><line x1="15" y1="20" x2="15" y2="23"></line><line x1="20" y1="9" x2="23" y2="9"></line><line x1="20" y1="14" x2="23" y2="14"></line><line x1="1" y1="9" x2="4" y2="9"></line><line x1="1" y1="14" x2="4" y2="14"></line></svg>

Before

Width:  |  Height:  |  Size: 667 B

View File

@@ -1,26 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<title>Scrypted Management Console</title>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Material+Icons">
<link href="https://fonts.googleapis.com/css2?family=Lato:wght@300;400;700&display=swap" rel="stylesheet">
<link href="https://fonts.googleapis.com/css2?family=Quicksand:wght@300;400;500;600;700&display=swap" rel="stylesheet">
</head>
<body>
<noscript>
<strong>We're sorry but web doesn't work properly without JavaScript enabled. Please enable it to continue.</strong>
</noscript>
<div id="app"></div>
<!-- built files will be auto injected -->
</body>
</html>

View File

@@ -1,45 +0,0 @@
{
"name": "Scrypted Management Console",
"short_name": "Scrypted",
"icons": [
{
"src": "https://koush.github.io/scrypted/plugins/core/ui/img/icons/icon-72x72.png",
"sizes": "72x72",
"type": "image/png"
},
{
"src": "https://koush.github.io/scrypted/plugins/core/ui/img/icons/icon-96x96.png",
"sizes": "96x96",
"type": "image/png"
},
{
"src": "https://koush.github.io/scrypted/plugins/core/ui/img/icons/icon-144x144.png",
"sizes": "144x144",
"type": "image/png"
},
{
"src": "https://koush.github.io/scrypted/plugins/core/ui/img/icons/icon-152x152.png",
"sizes": "152x152",
"type": "image/png"
},
{
"src": "https://koush.github.io/scrypted/plugins/core/ui/img/icons/icon-192x192.png",
"sizes": "192x192",
"type": "image/png"
},
{
"src": "https://koush.github.io/scrypted/plugins/core/ui/img/icons/icon-384x384.png",
"sizes": "384x384",
"type": "image/png"
},
{
"src": "https://koush.github.io/scrypted/plugins/core/ui/img/icons/icon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"start_url": "./index.html",
"display": "standalone",
"background_color": "#000000",
"theme_color": "#424242"
}

View File

@@ -1,2 +0,0 @@
User-agent: *
Disallow:

View File

@@ -1,6 +1,6 @@
# Home Assistant Addon Configuration
name: Scrypted
version: "v0.111.0-jammy-full"
version: "v0.118.0-jammy-full"
slug: scrypted
description: Scrypted is a high performance home video integration and automation platform
url: "https://github.com/koush/scrypted"

View File

@@ -18,4 +18,4 @@ ENV NODE_OPTIONS="--dns-result-order=ipv4first"
# if this base image changes, this version must be updated.
ENV SCRYPTED_BASE_VERSION="20240321"
CMD npm --prefix /server exec scrypted-serve
CMD ["/bin/sh", "-c", "ulimit -c 0; exec npm --prefix /server exec scrypted-serve"]

View File

@@ -7,8 +7,7 @@
# install script.
################################################################
ARG BASE="jammy"
ARG REPO="ubuntu"
FROM ${REPO}:${BASE} as header
FROM ubuntu:${BASE} as header
ENV DEBIAN_FRONTEND=noninteractive
@@ -72,9 +71,12 @@ RUN python3 -m pip install debugpy typing_extensions psutil
################################################################
FROM header as base
# intel opencl gpu for openvino
# intel opencl gpu and npu for openvino
RUN curl https://raw.githubusercontent.com/koush/scrypted/main/install/docker/install-intel-graphics.sh | bash
# Disable NPU on docker, because level-zero crashes openvino on older systems.
# RUN curl https://raw.githubusercontent.com/koush/scrypted/main/install/docker/install-intel-npu.sh | bash
# python 3.9 from ppa.
# 3.9 is the version with prebuilt support for tensorflow lite
RUN add-apt-repository -y ppa:deadsnakes/ppa && \

View File

@@ -17,9 +17,6 @@ RUN curl -fsSL https://deb.nodesource.com/gpgkey/nodesource-repo.gpg.key | gpg -
RUN echo "deb [signed-by=/etc/apt/keyrings/nodesource.gpg] https://deb.nodesource.com/node_"$NODE_VERSION".x nodistro main" | tee /etc/apt/sources.list.d/nodesource.list
RUN apt-get update && apt-get install -y nodejs
# intel opencl gpu for openvino
RUN curl https://raw.githubusercontent.com/koush/scrypted/main/install/docker/install-intel-graphics.sh | bash
ENV SCRYPTED_INSTALL_ENVIRONMENT="docker"
ENV SCRYPTED_CAN_RESTART="true"
ENV SCRYPTED_VOLUME="/server/volume"

View File

@@ -1,6 +1,9 @@
ARG BASE="ghcr.io/koush/scrypted-common:20-jammy-full"
FROM $BASE
ENV NVIDIA_DRIVER_CAPABILITIES=all
ENV NVIDIA_VISIBLE_DEVICES=all
# nvidia cudnn/libcublas etc.
# for some reason this is not provided by the nvidia container toolkit
RUN curl https://raw.githubusercontent.com/koush/scrypted/main/install/docker/install-nvidia-graphics.sh | bash

View File

@@ -48,4 +48,4 @@ ENV NODE_OPTIONS="--dns-result-order=ipv4first"
# if this base image changes, this version must be updated.
ENV SCRYPTED_BASE_VERSION="20240321"
CMD npm --prefix /server exec scrypted-serve
CMD ["/bin/sh", "-c", "ulimit -c 0; exec npm --prefix /server exec scrypted-serve"]

View File

@@ -19,6 +19,9 @@
services:
scrypted:
# LXC usage only
# lxc privileged: true
environment:
# Scrypted NVR Storage (Part 2 of 3)
@@ -29,30 +32,26 @@ services:
# section below.
# - SCRYPTED_NVR_VOLUME=/nvr
- SCRYPTED_WEBHOOK_UPDATE_AUTHORIZATION=Bearer SET_THIS_TO_SOME_RANDOM_TEXT
- SCRYPTED_WEBHOOK_UPDATE_AUTHORIZATION=Bearer ${WATCHTOWER_HTTP_API_TOKEN:-env_missing_fallback}
- SCRYPTED_WEBHOOK_UPDATE=http://localhost:10444/v1/update
# LXC usage only
# lxc - SCRYPTED_INSTALL_ENVIRONMENT=lxc-docker
# Avahi can be used for network discovery by passing in the host daemon
# or running the daemon inside the container. Choose one or the other.
# Uncomment next line to run avahi-daemon inside the container.
# See volumes and security_opt section below to use the host daemon.
# - SCRYPTED_DOCKER_AVAHI=true
# NVIDIA (Part 1 of 4)
# - NVIDIA_VISIBLE_DEVICES=all
# - NVIDIA_DRIVER_CAPABILITIES=all
# NVIDIA (Part 2 of 4)
# NVIDIA (Part 1 of 2)
# runtime: nvidia
# NVIDIA (Part 3 of 4) - Use NVIDIA image, and remove subsequent default image.
# NVIDIA (Part 2 of 2) - Use NVIDIA image, and remove subsequent default image.
# image: ghcr.io/koush/scrypted:nvidia
image: ghcr.io/koush/scrypted
volumes:
# NVIDIA (Part 4 of 4)
# - /etc/OpenCL/vendors/nvidia.icd:/etc/OpenCL/vendors/nvidia.icd
# Scrypted NVR Storage (Part 3 of 3)
# Modify to add the additional volume for Scrypted NVR.
@@ -77,6 +76,14 @@ services:
# Default volume for the Scrypted database. Typically should not be changed.
- ~/.scrypted/volume:/server/volume
# LXC usage only
# lxc - /var/run/docker.sock:/var/run/docker.sock
# lxc - /root/.scrypted/docker-compose.yml:/root/.scrypted/docker-compose.yml
# lxc - /root/.scrypted/docker-compose.sh:/root/.scrypted/docker-compose.sh
# lxc - /root/.scrypted/.env:/root/.scrypted/.env
# lxc - /mnt:/mnt
# Uncomment the following lines to use Avahi daemon from the host
# Without this, AppArmor will block the container's attempt to talk to Avahi via dbus
# security_opt:
@@ -120,12 +127,10 @@ services:
# watchtower manages updates for Scrypted.
watchtower:
environment:
- WATCHTOWER_HTTP_API_TOKEN=SET_THIS_TO_SOME_RANDOM_TEXT
- WATCHTOWER_HTTP_API_TOKEN=${WATCHTOWER_HTTP_API_TOKEN:-env_missing_fallback}
- WATCHTOWER_HTTP_API_UPDATE=true
- WATCHTOWER_SCOPE=scrypted
# remove the following line to never allow docker to auto update.
# this is not recommended.
- WATCHTOWER_HTTP_API_PERIODIC_POLLS=true
- WATCHTOWER_HTTP_API_PERIODIC_POLLS=${WATCHTOWER_HTTP_API_PERIODIC_POLLS:-true}
image: containrrr/watchtower
container_name: scrypted-watchtower
restart: unless-stopped

View File

@@ -1,5 +1,9 @@
#!/bin/bash
# disable core dumps.
# this doesn't disable core dumps on the scrypted service itself, only stuff run by init.
ulimit -c 0
if [[ "${SCRYPTED_DOCKER_AVAHI}" != "true" ]]; then
echo "SCRYPTED_DOCKER_AVAHI != true, won't manage dbus nor avahi-daemon" >/dev/stderr
exit 0

View File

@@ -1,38 +1,56 @@
if [ "$(uname -m)" = "x86_64" ]
if [ "$(uname -m)" != "x86_64" ]
then
# this script previvously apt install intel-media-va-driver-non-free, but that seems to no longer be necessary.
# the intel provided script is disabled since it does not work with the 6.8 kernel in Ubuntu 24.04 or Proxmox 8.2.
# manual installation of the Intel graphics stuff is required.
# echo "Installing Intel graphics packages."
# apt-get update && apt-get install -y gpg-agent &&
# rm -f /usr/share/keyrings/intel-graphics.gpg &&
# curl -L https://repositories.intel.com/graphics/intel-graphics.key | gpg --dearmor --yes --output /usr/share/keyrings/intel-graphics.gpg &&
# echo 'deb [arch=amd64,i386 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/graphics/ubuntu jammy arc' | tee /etc/apt/sources.list.d/intel.gpu.jammy.list &&
# apt-get -y update &&
# apt-get -y install intel-opencl-icd &&
# apt-get -y dist-upgrade;
# manual installation
# https://github.com/intel/compute-runtime/releases/tag/24.13.29138.7
rm -rf /tmp/neo && mkdir -p /tmp/neo && cd /tmp/neo &&
apt-get install -y ocl-icd-libopencl1 &&
curl -O -L https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.16695.4/intel-igc-core_1.0.16695.4_amd64.deb &&
curl -O -L https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.16695.4/intel-igc-opencl_1.0.16695.4_amd64.deb &&
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.17.29377.6/intel-level-zero-gpu-dbgsym_1.3.29377.6_amd64.ddeb &&
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.17.29377.6/intel-level-zero-gpu_1.3.29377.6_amd64.deb &&
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.17.29377.6/intel-opencl-icd-dbgsym_24.17.29377.6_amd64.ddeb &&
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.17.29377.6/intel-opencl-icd_24.17.29377.6_amd64.deb &&
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.17.29377.6/libigdgmm12_22.3.19_amd64.deb &&
dpkg -i *.deb &&
cd /tmp && rm -rf /tmp/neo &&
apt-get -y dist-upgrade;
exit $?
else
echo "Intel graphics will not be installed on this architecture."
exit 0
fi
exit 0
# no errors beyond this point
set -e
# the intel provided script is disabled since it does not work with the 6.8 kernel in Ubuntu 24.04 or Proxmox 8.2.
# manual installation of the Intel graphics stuff is required.
# echo "Installing Intel graphics packages."
# apt-get update && apt-get install -y gpg-agent &&
# rm -f /usr/share/keyrings/intel-graphics.gpg &&
# curl -L https://repositories.intel.com/graphics/intel-graphics.key | gpg --dearmor --yes --output /usr/share/keyrings/intel-graphics.gpg &&
# echo 'deb [arch=amd64,i386 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/graphics/ubuntu jammy arc' | tee /etc/apt/sources.list.d/intel.gpu.jammy.list &&
# apt-get -y update &&
# apt-get -y install intel-opencl-icd &&
# apt-get -y dist-upgrade;
# need intel-media-va-driver-non-free, but all the other intel packages are installed from Intel github.
echo "Installing Intel graphics packages."
apt-get update && apt-get install -y gpg-agent &&
rm -f /usr/share/keyrings/intel-graphics.gpg &&
curl -L https://repositories.intel.com/graphics/intel-graphics.key | gpg --dearmor --yes --output /usr/share/keyrings/intel-graphics.gpg &&
echo 'deb [arch=amd64,i386 signed-by=/usr/share/keyrings/intel-graphics.gpg] https://repositories.intel.com/graphics/ubuntu jammy arc' | tee /etc/apt/sources.list.d/intel.gpu.jammy.list &&
apt-get -y update &&
apt-get -y install intel-media-va-driver-non-free &&
apt-get -y dist-upgrade;
# manual installation
# https://github.com/intel/compute-runtime/releases/tag/24.13.29138.7
rm -rf /tmp/gpu && mkdir -p /tmp/gpu && cd /tmp/gpu
apt-get install -y ocl-icd-libopencl1
curl -O -L https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17537.20/intel-igc-core_1.0.17537.20_amd64.deb
curl -O -L https://github.com/intel/intel-graphics-compiler/releases/download/igc-1.0.17537.20/intel-igc-opencl_1.0.17537.20_amd64.deb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-level-zero-gpu-dbgsym_1.3.30872.22_amd64.ddeb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-level-zero-gpu-legacy1-dbgsym_1.3.30872.22_amd64.ddeb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-level-zero-gpu-legacy1_1.3.30872.22_amd64.deb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-level-zero-gpu_1.3.30872.22_amd64.deb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-opencl-icd-dbgsym_24.35.30872.22_amd64.ddeb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-opencl-icd-legacy1-dbgsym_24.35.30872.22_amd64.ddeb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-opencl-icd-legacy1_24.35.30872.22_amd64.deb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/intel-opencl-icd_24.35.30872.22_amd64.deb
curl -O -L https://github.com/intel/compute-runtime/releases/download/24.35.30872.22/libigdgmm12_22.5.0_amd64.deb
dpkg -i *.deb
cd /tmp && rm -rf /tmp/gpu
apt-get -y dist-upgrade

View File

@@ -0,0 +1,69 @@
if [ "$(uname -m)" != "x86_64" ]
then
echo "Intel NPU will not be installed on this architecture."
exit 0
fi
UBUNTU_22_04=$(lsb_release -r | grep "22.04")
UBUNTU_24_04=$(lsb_release -r | grep "24.04")
if [ -z "$UBUNTU_22_04" ]
then
# proxmox is compatible with ubuntu 22.04, check for /etc/pve directory
if [ -d "/etc/pve" ]
then
UBUNTU_22_04=true
fi
fi
# needs either ubuntu 22.0.4 or 24.04
if [ -z "$UBUNTU_22_04" ] && [ -z "$UBUNTU_24_04" ]
then
echo "Intel NPU will not be installed. Ubuntu version could not be detected when checking lsb-release and /etc/os-release."
exit 0
fi
dpkg --purge --force-remove-reinstreq intel-driver-compiler-npu intel-fw-npu intel-level-zero-npu
# no errors beyond this point
set -e
rm -rf /tmp/npu && mkdir -p /tmp/npu && cd /tmp/npu
# different npu downloads for ubuntu versions
if [ -n "$UBUNTU_22_04" ]
then
curl -O -L https://github.com/intel/linux-npu-driver/releases/download/v1.8.0/intel-driver-compiler-npu_1.8.0.20240916-10885588273_ubuntu22.04_amd64.deb
# firmware can only be installed on host. will cause problems inside container.
if [ -n "$INTEL_FW_NPU" ]
then
curl -O -L https://github.com/intel/linux-npu-driver/releases/download/v1.8.0/intel-fw-npu_1.8.0.20240916-10885588273_ubuntu22.04_amd64.deb
fi
curl -O -L https://github.com/intel/linux-npu-driver/releases/download/v1.8.0/intel-level-zero-npu_1.8.0.20240916-10885588273_ubuntu22.04_amd64.deb
else
curl -O -L https://github.com/intel/linux-npu-driver/releases/download/v1.8.0/intel-driver-compiler-npu_1.8.0.20240916-10885588273_ubuntu24.04_amd64.deb
if [ -n "$INTEL_FW_NPU" ]
then
curl -O -L https://github.com/intel/linux-npu-driver/releases/download/v1.8.0/intel-fw-npu_1.8.0.20240916-10885588273_ubuntu24.04_amd64.deb
fi
curl -O -L https://github.com/intel/linux-npu-driver/releases/download/v1.8.0/intel-level-zero-npu_1.8.0.20240916-10885588273_ubuntu24.04_amd64.deb
fi
curl -O -L https://github.com/oneapi-src/level-zero/releases/download/v1.17.6/level-zero_1.17.6+u22.04_amd64.deb
curl -O -L https://github.com/oneapi-src/level-zero/releases/download/v1.17.6/level-zero-devel_1.17.6+u22.04_amd64.deb
apt -y update
apt -y install libtbb12
dpkg -i *.deb
cd /tmp && rm -rf /tmp/npu
apt-get -y dist-upgrade
if [ -n "$INTEL_FW_NPU" ]
then
echo
echo "###############################################################################"
echo "Intel NPU firmware was installed. Reboot the host to complete the installation."
echo "###############################################################################"
fi

View File

@@ -0,0 +1,40 @@
UBUNTU_22_04=$(lsb_release -r | grep "22.04")
UBUNTU_24_04=$(lsb_release -r | grep "24.04")
set -e
# https://developer.nvidia.com/cuda-downloads?target_os=Linux&target_arch=x86_64&Distribution=Ubuntu&target_version=24.04&target_type=deb_network
# need this apt for nvidia-utils
# needs either ubuntu 22.0.4 or 24.04
if [ -z "$UBUNTU_22_04" ] && [ -z "$UBUNTU_24_04" ]
then
echo "NVIDIA container toolkit can not be installed. Ubuntu version could not be detected when checking lsb-release and /etc/os-release."
exit 1
fi
if [ -n "$UBUNTU_22_04" ]
then
distro="ubuntu2204"
else
distro="ubuntu2404"
fi
apt update -q \
&& apt install -y wget \
&& wget -qO /cuda-keyring.deb https://developer.download.nvidia.com/compute/cuda/repos/$distro/$(uname -m)/cuda-keyring_1.1-1_all.deb \
&& dpkg -i /cuda-keyring.deb;
# https://docs.nvidia.com/datacenter/cloud-native/container-toolkit/latest/install-guide.html
apt -y update
apt -y install gpg
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | gpg --yes --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
&& curl -s -L https://nvidia.github.io/libnvidia-container/stable/deb/nvidia-container-toolkit.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
apt -y update
# is there a way to get a versioned package automatically?
apt -y install nvidia-utils-560
apt -y install nvidia-container-toolkit
nvidia-ctk runtime configure --runtime=docker
nvidia-ctk config --set nvidia-container-cli.no-cgroups --in-place
systemctl restart docker

View File

@@ -1,14 +1,52 @@
if [ "$(uname -m)" = "x86_64" ]
then
UBUNTU_22_04=$(lsb_release -r | grep "22.04")
UBUNTU_24_04=$(lsb_release -r | grep "24.04")
# needs either ubuntu 22.0.4 or 24.04
if [ -z "$UBUNTU_22_04" ] && [ -z "$UBUNTU_24_04" ]
then
echo "NVIDIA graphics package can not be installed. Ubuntu version could not be detected when checking lsb-release and /etc/os-release."
exit 1
fi
if [ -n "$UBUNTU_22_04" ]
then
distro="ubuntu2204"
else
distro="ubuntu2404"
fi
echo "Installing NVIDIA graphics packages."
apt update -q \
&& apt install -y wget \
&& wget -qO /cuda-keyring.deb https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/$(uname -m)/cuda-keyring_1.1-1_all.deb \
&& wget -qO /cuda-keyring.deb https://developer.download.nvidia.com/compute/cuda/repos/$distro/$(uname -m)/cuda-keyring_1.1-1_all.deb \
&& dpkg -i /cuda-keyring.deb \
&& apt update -q \
&& apt install -y cuda-nvcc-11-8 libcublas-11-8 libcudnn8 cuda-libraries-11-8 \
&& apt install -y cuda-nvcc-12-4 libcublas-12-4 libcudnn8 cuda-libraries-12-4;
exit $?
&& apt install -y cuda-nvcc-12-6 libcublas-12-6 libcudnn9-cuda-12 cuda-libraries-12-6;
if [ "$?" != "0" ]
then
echo "Error: NVIDIA graphics packages failed to install."
exit 1
fi
# Update: the libnvidia-opencl.so.1 file is not present in the container image, it is
# mounted via the nvidia container runtime. This is why the following check is commented out.
# this file is present but for some reason the icd file is not created by nvidia runtime.
# if [ ! -f "/usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.1" ]
# then
# echo "Error: NVIDIA OpenCL library not found."
# exit 1
# fi
# the container runtime doesn't mount this file for some reason. seems to be a bug.
# https://github.com/NVIDIA/nvidia-container-toolkit/issues/682
# but the contents are simply the .so file, which is a symlink the nvidia runtime
# will mount in.
mkdir -p /etc/OpenCL/vendors/
echo "libnvidia-opencl.so.1" > /etc/OpenCL/vendors/nvidia.icd
else
echo "NVIDIA graphics will not be installed on this architecture."
fi

View File

@@ -1,5 +1,11 @@
#!/usr/bin/env bash
if [ "$SCRYPTED_LXC" ]
then
export SERVICE_USER="root"
export SCRYPTED_NONINTERACTIVE="true"
fi
if [ -z "$SERVICE_USER" ]
then
echo "Scrypted SERVICE_USER environment variable was not specified. Service will not be installed."
@@ -7,6 +13,12 @@ then
fi
function readyn() {
if [ ! -z "$SCRYPTED_NONINTERACTIVE" ]
then
yn="y"
return
fi
while true; do
read -p "$1 (y/n) " yn
case $yn in
@@ -33,6 +45,11 @@ systemctl disable scrypted.service 2> /dev/null
USER_HOME=$(eval echo ~$SERVICE_USER)
SCRYPTED_HOME=$USER_HOME/.scrypted
mkdir -p $SCRYPTED_HOME
# remove various things from a previous local install.
rm -rf $SCRYPTED_HOME/node_modules
rm -rf $SCRYPTED_HOME/install.json
rm -rf $SCRYPTED_HOME/package.json
rm -rf $SCRYPTED_HOME/package-lock.json
set -e
cd $SCRYPTED_HOME
@@ -46,13 +63,30 @@ then
usermod -aG docker $SERVICE_USER
fi
WATCHTOWER_HTTP_API_TOKEN=$(echo $RANDOM | md5sum)
WATCHTOWER_HTTP_API_TOKEN=$(echo $RANDOM | md5sum | head -c 32)
echo "WATCHTOWER_HTTP_API_TOKEN=$WATCHTOWER_HTTP_API_TOKEN" > $SCRYPTED_HOME/.env
# remove the following line from .env to disable autoupdates.
# this is not recommended.
echo "WATCHTOWER_HTTP_API_PERIODIC_POLLS=true" >> $SCRYPTED_HOME/.env
DOCKER_COMPOSE_YML=$SCRYPTED_HOME/docker-compose.yml
curl -s https://raw.githubusercontent.com/koush/scrypted/main/install/docker/docker-compose.yml > $DOCKER_COMPOSE_YML
echo "Created $DOCKER_COMPOSE_YML"
curl -s https://raw.githubusercontent.com/koush/scrypted/main/install/docker/docker-compose.yml | sed s/SET_THIS_TO_SOME_RANDOM_TEXT/"$(echo $RANDOM | md5sum | head -c 32)"/g > $DOCKER_COMPOSE_YML
if [ -d /dev/dri ]
if [ -z "$SCRYPTED_LXC" ]
then
sed -i 's/'#' "\/dev\/dri/"\/dev\/dri/g' $DOCKER_COMPOSE_YML
if [ -d /dev/dri ]
then
sed -i 's/'#' "\/dev\/dri/"\/dev\/dri/g' $DOCKER_COMPOSE_YML
fi
else
# uncomment lxc specific stuff
sed -i 's/'#' lxc //g' $DOCKER_COMPOSE_YML
# never restart, systemd will handle it
sed -i 's/restart: unless-stopped/restart: no/g' $DOCKER_COMPOSE_YML
sudo systemctl stop apparmor || true
sudo apt -y purge apparmor || true
fi
readyn "Install avahi-daemon? This is the recommended for reliable HomeKit discovery and pairing."
@@ -66,7 +100,7 @@ then
fi
echo "Setting permissions on $SCRYPTED_HOME"
chown -R $SERVICE_USER $SCRYPTED_HOME
chown -R $SERVICE_USER $SCRYPTED_HOME || true
set +e
@@ -79,8 +113,41 @@ set -e
echo "docker compose pull"
sudo -u $SERVICE_USER docker compose pull
echo "docker compose up -d"
sudo -u $SERVICE_USER docker compose up -d
if [ -z "$SCRYPTED_LXC" ]
then
echo "docker compose up -d"
sudo -u $SERVICE_USER docker compose up -d
else
export DOCKER_COMPOSE_SH=$SCRYPTED_HOME/docker-compose.sh
curl https://raw.githubusercontent.com/koush/scrypted/main/install/proxmox/docker-compose.sh > $DOCKER_COMPOSE_SH
chmod +x $DOCKER_COMPOSE_SH
cat > /etc/systemd/system/scrypted.service <<EOT
[Unit]
Description=Scrypted service
After=network.target
[Service]
User=root
Group=root
Type=simple
ExecStart=$DOCKER_COMPOSE_SH
Restart=always
RestartSec=3
StandardOutput=null
StandardError=null
[Install]
WantedBy=multi-user.target
EOT
systemctl daemon-reload
systemctl enable scrypted.service
systemctl restart scrypted.service
fi
echo
echo
@@ -91,5 +158,5 @@ echo "Note that it is https and that you'll be asked to approve/ignore the websi
echo
echo
echo "Optional:"
echo "Scrypted NVR Recording storage directory can be configured with an additional script:"
echo "https://docs.scrypted.app/scrypted-nvr/installation.html#docker-volume"
echo "Scrypted NVR Recording storage directory can be configured with an additional script located at:"
echo "https://docs.scrypted.app/scrypted-nvr/recording-storage.html#docker-volume"

View File

@@ -128,7 +128,7 @@ then
set -e
removescryptedfstab
mkdir -p /mnt/scrypted-nvr
echo "PARTLABEL=scrypted-nvr /mnt/scrypted-nvr ext4 defaults,nofail 0 0" >> /etc/fstab
echo "PARTLABEL=scrypted-nvr /mnt/scrypted-nvr ext4 defaults,nofail,noatime 0 0" >> /etc/fstab
mount -a
systemctl daemon-reload
set +e

View File

@@ -3,9 +3,12 @@
################################################################
FROM header as base
# intel opencl gpu for openvino
# intel opencl gpu and npu for openvino
RUN curl https://raw.githubusercontent.com/koush/scrypted/main/install/docker/install-intel-graphics.sh | bash
# Disable NPU on docker, because level-zero crashes openvino on older systems.
# RUN curl https://raw.githubusercontent.com/koush/scrypted/main/install/docker/install-intel-npu.sh | bash
# python 3.9 from ppa.
# 3.9 is the version with prebuilt support for tensorflow lite
RUN add-apt-repository -y ppa:deadsnakes/ppa && \

View File

@@ -0,0 +1,23 @@
#!/bin/bash
cd /root/.scrypted
# always immediately upgrade everything in case there's a broken update.
# this will also be preferable for troubleshooting via lxc reboot.
export DEBIAN_FRONTEND=noninteractive
(apt -y --fix-broken install && (yes | dpkg --configure -a) && apt -y update && apt -y dist-upgrade) &
# foreground pull if requested.
if [ -e "volume/.pull" ]
then
rm -rf volume/.pull
docker compose pull && docker container prune -f && docker image prune -a -f
else
# always background pull in case there's a broken image.
(docker compose pull && docker container prune -f && docker image prune -a -f) &
fi
# do not daemonize, when it exits, systemd will restart it.
# force a recreate as .env may have changed.
# furthermore force recreate gets the container back into a known state
# which is preferable in case the user has made manual changes and then restarts.
WATCHTOWER_HTTP_API_TOKEN=$(echo $RANDOM | md5sum | head -c 32) docker compose up --force-recreate --abort-on-container-exit

View File

@@ -1,3 +1,11 @@
PCT=$(which pct)
if [ -z "$PCT" ]
then
echo "pct command not found. This script must be run on the Proxmox host, not a container."
echo "Installation Documentation: https://docs.scrypted.app/installation.html#proxmox-ve"
exit 1
fi
function readyn() {
while true; do
read -p "$1 (y/n) " yn
@@ -10,13 +18,20 @@ function readyn() {
}
cd /tmp
SCRYPTED_VERSION=v0.96.0
SCRYPTED_VERSION=v0.116.0
SCRYPTED_TAR_ZST=scrypted-$SCRYPTED_VERSION.tar.zst
if [ -z "$VMID" ]
then
VMID=10443
fi
if [ -n "$SCRYPTED_RESTORE" ]
then
RESTORE_VMID=$VMID
VMID=10444
pct destroy $VMID 2>&1 > /dev/null
fi
echo "Downloading scrypted container backup."
if [ ! -f "$SCRYPTED_TAR_ZST" ]
then
@@ -49,7 +64,7 @@ then
echo "'local-lvm' or 'local-zfs'."
echo ""
echo "#############################################################################"
echo "Paste the following command into this shell to install to local-lvm instead:"
echo -e "\033[32mPaste the following command into this shell to install to local-lvm instead:\033[0m"
echo ""
echo "bash $0 --storage local-lvm"
echo "#############################################################################"
@@ -75,17 +90,57 @@ else
echo "$CONF not found? Start on boot must be enabled manually."
fi
echo "Adding udev rule: /etc/udev/rules.d/65-scrypted.rules"
if [ -n "$SCRYPTED_RESTORE" ]
then
readyn "Running this script will reset Scrypted to a factory state while preserving existing data. IT IS RECOMMENDED TO CREATE A BACKUP FIRST. Are you sure you want to continue?"
if [ "$yn" != "y" ]
then
exit 1
fi
echo "Preparing rootfs reset..."
# this copies the
pct set 10444 --delete mp0 && pct set 10444 --delete unused0 && pct move-volume $RESTORE_VMID mp0 --target-vmid 10444 --target-volume mp0
rm *.tar
vzdump 10444 --dumpdir /tmp
VMID=$RESTORE_VMID
echo "Moving data volume to backup..."
pct restore $VMID *.tar $@
pct destroy 10444
fi
readyn "Add udev rule for hardware acceleration? This may conflict with existing rules."
if [ "$yn" == "y" ]
then
echo "Adding udev rule: /etc/udev/rules.d/65-scrypted.rules"
sh -c "echo 'SUBSYSTEM==\"apex\", MODE=\"0666\"' > /etc/udev/rules.d/65-scrypted.rules"
sh -c "echo 'KERNEL==\"renderD128\", MODE=\"0666\"' >> /etc/udev/rules.d/65-scrypted.rules"
sh -c "echo 'KERNEL==\"card0\", MODE=\"0666\"' >> /etc/udev/rules.d/65-scrypted.rules"
sh -c "echo 'SUBSYSTEM==\"drm\", MODE=\"0666\"' >> /etc/udev/rules.d/65-scrypted.rules"
sh -c "echo 'SUBSYSTEM==\"accel\", MODE=\"0666\"' >> /etc/udev/rules.d/65-scrypted.rules"
sh -c "echo 'SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"1a6e\", ATTRS{idProduct}==\"089a\", MODE=\"0666\"' >> /etc/udev/rules.d/65-scrypted.rules"
sh -c "echo 'SUBSYSTEM==\"usb\", ATTRS{idVendor}==\"18d1\", ATTRS{idProduct}==\"9302\", MODE=\"0666\"' >> /etc/udev/rules.d/65-scrypted.rules"
udevadm control --reload-rules && udevadm trigger
fi
# check if intel
INTEL=$(cat /proc/cpuinfo | grep GenuineIntel)
if [ ! -z "$INTEL" ]
then
readyn "Install intel-microcode package? This will update your CPU and GPU firmware."
if [ "$yn" == "y" ]
then
echo "Installing intel-microcode..."
# remove it first to allow reinsertion
sed -i 's/main contrib non-free-firmware/main/g' /etc/apt/sources.list
sed -i 's/main/main contrib non-free-firmware/g' /etc/apt/sources.list
apt update
apt install -y intel-microcode
echo "#############################"
echo "System Reboot is recommended."
echo "#############################"
fi
fi
echo "Scrypted setup is complete and the container resources can be started."
echo "Scrypted NVR users should provide at least 4 cores and 16GB RAM prior to starting."

BIN
install/proxmox/lxc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

View File

@@ -0,0 +1,63 @@
#!/bin/bash
NVR_STORAGE=$1
DISK_TYPE="large"
if [ ! -z "$FAST_DISK" ]
then
DISK_TYPE="fast"
fi
if [ -z "$NVR_STORAGE" ]; then
echo ""
echo "Error: Proxmox Directory Disk not provided. Usage:"
echo ""
echo "bash $0 <proxmox-directory-disk>"
echo ""
exit 1
fi
if [ -z "$VMID" ]
then
VMID="10443"
fi
FILE="/etc/pve/lxc/$VMID.conf"
# valdiate file exists
if [ ! -f "$FILE" ]; then
echo "Error: $FILE not found."
echo "If the Scrypted container id is not 10443, please set the VMID environment variable prior to running this script."
exit 1
fi
STORAGE="/mnt/pve/$NVR_STORAGE"
if [ ! -d "$STORAGE" ]
then
echo "Error: $STORAGE not found."
echo "The Proxmox Directory Storage must be created using the UI prior to running this script."
exit 1
fi
# use subdirectory doesn't conflict with Proxmox storage of backups etc.
STORAGE="$STORAGE/mounts/scrypted-nvr"
# create the hidden folder that can be used as a marker.
mkdir -p $STORAGE/.nvr
chmod 0777 $STORAGE
echo "Stopping Scrypted..."
pct stop "$VMID"
echo "Modifying $FILE."
if [ -z "$ADD_DISK" ]
then
echo "Removing previous $DISK_TYPE lxc.mount.entry."
sed -i "/mnt\/nvr\/$DISK_TYPE/d" "$FILE"
fi
echo "Adding new $DISK_TYPE lxc.mount.entry."
echo "lxc.mount.entry: $STORAGE mnt/nvr/$DISK_TYPE/$NVR_STORAGE none bind,optional,create=dir" >> "$FILE"
echo "Starting Scrypted..."
pct start $VMID

View File

@@ -84,15 +84,33 @@ export function createAuthFetch<B, M>(
if (initialHeader && !hasHeader(headers, 'Authorization'))
setHeader(headers, 'Authorization', initialHeader);
const controller = new AbortController();
options.signal?.addEventListener('abort', () => controller.abort(options.signal?.reason));
const initialResponse = await h({
...options,
ignoreStatusCode: true,
signal: controller.signal,
// need to intercept the status code to check for 401.
// all other status codes will be handled according to the initial request options.
checkStatusCode(statusCode) {
// can handle a 401 if an credential is provided.
// however, not providing a credential is also valid, and should
// fall through to the normal response handling which may be interested
// in the 401 response.
if (statusCode === 401 && options.credential)
return true;
if (options?.checkStatusCode === undefined || options?.checkStatusCode) {
const checker = typeof options?.checkStatusCode === 'function' ? options.checkStatusCode : checkStatus;
return checker(statusCode);
}
return true;
},
responseType: 'readable',
});
if (initialResponse.statusCode !== 401 || !options.credential) {
if (!options?.ignoreStatusCode)
checkStatus(initialResponse.statusCode);
// if it's not a 401, just return the response.
if (initialResponse.statusCode !== 401) {
return {
...initialResponse,
body: await parser(initialResponse.body, options.responseType),

View File

@@ -21,7 +21,7 @@
],
"preLaunchTask": "npm: build",
"args": [
"login",
"serve",
],
"sourceMaps": true,
"resolveSourceMapLocations": [

View File

@@ -1,12 +1,12 @@
{
"name": "scrypted",
"version": "1.3.16",
"version": "1.3.20",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "scrypted",
"version": "1.3.16",
"version": "1.3.20",
"license": "ISC",
"dependencies": {
"@scrypted/client": "^1.3.3",

View File

@@ -1,6 +1,6 @@
{
"name": "scrypted",
"version": "1.3.16",
"version": "1.3.20",
"description": "",
"main": "./dist/packages/cli/src/main.js",
"bin": {

View File

@@ -10,6 +10,7 @@ import semver from 'semver';
import { httpFetch } from '../../../server/src/fetch/http-fetch';
import { installServe, serveMain } from './service';
import { connectShell } from './shell';
import { convertRtspToMp4, printRtspUsage } from './rtsp-file';
if (!semver.gte(process.version, '16.0.0')) {
throw new Error('"node" version out of date. Please update node to v16 or higher.')
@@ -173,6 +174,14 @@ async function main() {
});
sdk.disconnect();
}
else if (process.argv[2] === 'rtsp') {
if (!process.argv[3]) {
printRtspUsage();
process.exit(1);
}
await convertRtspToMp4(process.argv[3], process.argv[4]);
}
else if (process.argv[2] === 'create-cert-json' && process.argv.length === 5) {
const key = fs.readFileSync(process.argv[3]).toString();
const cert = fs.readFileSync(process.argv[4]).toString();

View File

@@ -0,0 +1,72 @@
import child_process from 'child_process';
import fs from 'fs';
import path from 'path';
import { listenSingleRtspClient } from '../../../common/src/rtsp-server';
import { parseSdp } from '../../../common/src/sdp-utils';
import { once } from 'events';
export async function convertRtspToMp4(rtspFile: string, sessionFile?: string) {
// rtsp file will be in roughly:
// /nvr/scrypted-[id]/[session-timestamp]/[hour-timestamp]/[segment-timestamp].rtsp
// sdp can be found in
// /nvr/scrypted-[id]/[session-timestamp]/session.json
// or legacy:
// /nvr/scrypted-[id]/[session-timestamp]/session.sdp
const sessionDir = path.dirname(path.dirname(rtspFile));
let sdp: string;
let sessionJson = path.join(sessionDir, 'session.json');
if (!fs.existsSync(sessionJson) && sessionFile)
sessionJson = sessionFile.endsWith('.json') && sessionFile;
let sessionSdp = path.join(sessionDir, 'session.sdp');
if (!fs.existsSync(sessionSdp) && sessionFile)
sessionSdp = sessionFile.endsWith('.sdp') && sessionFile;
if (fs.existsSync(sessionJson)) {
sdp = JSON.parse(fs.readFileSync(sessionJson).toString()).sdp;
}
else if (fs.existsSync(sessionSdp)) {
sdp = fs.readFileSync(sessionSdp).toString();
}
else {
console.error('Could not find session sdp. Ensure the rtsp directory structure is intact or specify the path to the session file.');
console.error();
printRtspUsage();
process.exit(1);
}
const parsedSdp = parseSdp(sdp);
const hasAudio = parsedSdp.msections.some(msection => msection.type === 'audio');
const rtspContents = fs.readFileSync(rtspFile);
const clientPromise = await listenSingleRtspClient();
clientPromise.rtspServerPromise.then(async rtspServer => {
rtspServer.sdp = sdp;
await rtspServer.handlePlayback();
console.log('playing')
rtspServer.client.write(rtspContents);
rtspServer.client.end();
});
const mp4 = rtspFile + '.mp4';
const cp = child_process.spawn('ffmpeg', [
'-y',
'-i', clientPromise.url,
'-vcodec', 'copy',
...(hasAudio ? ['-acodec', 'aac'] : []),
mp4,
], {
stdio: 'inherit',
});
await once(cp, 'exit');
console.log('mp4 written to:', mp4);
}
export function printRtspUsage() {
console.log('usage: npx rtsp /path/to/nvr/file.rtsp [/path/to/nvr/session.json | /path/to/nvr/session.sdp]');
}

View File

@@ -12,6 +12,7 @@ async function sleep(ms: number) {
const EXIT_FILE = '.exit';
const UPDATE_FILE = '.update';
const VERSION_FILE = '.version';
async function runCommand(command: string, ...args: string[]) {
if (os.platform() === 'win32') {
@@ -117,6 +118,15 @@ export async function installServe(installVersion: string, ignoreError?: boolean
}
export async function serveMain(installVersion?: string) {
const { installDir, volume } = cwdInstallDir();
if (!installVersion) {
try {
installVersion = fs.readFileSync(path.join(volume, VERSION_FILE)).toString().trim();
}
catch (e) {
}
}
const options = ((): { install: true; version: string } | { install: false } => {
if (installVersion) {
console.log(`Installing @scrypted/server@${installVersion}`);
@@ -139,7 +149,6 @@ export async function serveMain(installVersion?: string) {
}
})();
const { installDir, volume } = cwdInstallDir();
if (options.install) {
await installServe(options.version, true);

View File

@@ -9,8 +9,10 @@
"inlineSources": true,
"declaration": true,
"moduleResolution": "Node16",
"strict": true
},
"strict": true,
"strictPropertyInitialization": false,
"strictNullChecks": false,
},
"include": [
"src/**/*"
],

View File

@@ -1,24 +1,24 @@
{
"name": "@scrypted/client",
"version": "1.3.5",
"version": "1.3.6",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@scrypted/client",
"version": "1.3.5",
"version": "1.3.6",
"license": "ISC",
"dependencies": {
"@scrypted/types": "^0.3.27",
"engine.io-client": "^6.5.3",
"follow-redirects": "^1.15.6",
"rimraf": "^5.0.5"
"@scrypted/types": "^0.3.60",
"engine.io-client": "^6.6.1",
"follow-redirects": "^1.15.9",
"rimraf": "^6.0.1"
},
"devDependencies": {
"@types/ip": "^1.1.3",
"@types/node": "^20.11.30",
"@types/node": "^22.7.4",
"ts-node": "^10.9.2",
"typescript": "^5.4.3"
"typescript": "^5.6.2"
}
},
"node_modules/@cspotcode/source-map-support": {
@@ -74,19 +74,10 @@
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@pkgjs/parseargs": {
"version": "0.11.0",
"resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
"integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
"optional": true,
"engines": {
"node": ">=14"
}
},
"node_modules/@scrypted/types": {
"version": "0.3.27",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.3.27.tgz",
"integrity": "sha512-XNtlqzqt6rHyNYwWrz3iiickh1h9ACwcLC3rfwxUbFk/Vq/UbDZgp0kGyj9UW6eLVNHzWFSE2dKqyyDS6V2KAg=="
"version": "0.3.60",
"resolved": "https://registry.npmjs.org/@scrypted/types/-/types-0.3.60.tgz",
"integrity": "sha512-oapFYQvyHLp0odCSx//USNnGNegS9ZL6a1HFIZzjDdMj2MNszTqiucAcu/wAlBwqjgURlP4/8xeLGVHEa4S2uQ=="
},
"node_modules/@socket.io/component-emitter": {
"version": "3.1.0",
@@ -127,12 +118,12 @@
}
},
"node_modules/@types/node": {
"version": "20.11.30",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.30.tgz",
"integrity": "sha512-dHM6ZxwlmuZaRmUPfv1p+KrdD1Dci04FbdEm/9wEMouFqxYoFl5aMkt0VMAUtYRQDyYvD41WJLukhq/ha3YuTw==",
"version": "22.7.4",
"resolved": "https://registry.npmjs.org/@types/node/-/node-22.7.4.tgz",
"integrity": "sha512-y+NPi1rFzDs1NdQHHToqeiX2TIS79SWEAw9GYhkkx8bD0ChpfqC+n2j5OXOCpzfojBEBt6DnEnnG9MY0zk1XLg==",
"dev": true,
"dependencies": {
"undici-types": "~5.26.4"
"undici-types": "~6.19.2"
}
},
"node_modules/acorn": {
@@ -157,9 +148,9 @@
}
},
"node_modules/ansi-regex": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz",
"integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==",
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"engines": {
"node": ">=12"
},
@@ -268,15 +259,15 @@
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg=="
},
"node_modules/engine.io-client": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.5.3.tgz",
"integrity": "sha512-9Z0qLB0NIisTRt1DZ/8U2k12RJn8yls/nXMZLn+/N8hANT3TcYjKFKcwbw5zFQiN4NTde3TSY9zb79e1ij6j9Q==",
"version": "6.6.1",
"resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.1.tgz",
"integrity": "sha512-aYuoak7I+R83M/BBPIOs2to51BmFIpC1wZe6zZzMrT2llVsHy5cvcmdsJgP2Qz6smHu+sD9oexiSUAVd8OfBPw==",
"dependencies": {
"@socket.io/component-emitter": "~3.1.0",
"debug": "~4.3.1",
"engine.io-parser": "~5.2.1",
"ws": "~8.11.0",
"xmlhttprequest-ssl": "~2.0.0"
"ws": "~8.17.1",
"xmlhttprequest-ssl": "~2.1.1"
}
},
"node_modules/engine.io-parser": {
@@ -288,9 +279,9 @@
}
},
"node_modules/follow-redirects": {
"version": "1.15.6",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
"integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
"version": "1.15.9",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
"integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
"funding": [
{
"type": "individual",
@@ -307,9 +298,9 @@
}
},
"node_modules/foreground-child": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz",
"integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==",
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
"integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^4.0.1"
@@ -322,21 +313,22 @@
}
},
"node_modules/glob": {
"version": "10.3.10",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz",
"integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==",
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.0.tgz",
"integrity": "sha512-9UiX/Bl6J2yaBbxKoEBRm4Cipxgok8kQYcOPEhScPwebu2I0HoQOuYdIO6S3hLuWoZgpDpwQZMzTFxgpkyT76g==",
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^2.3.5",
"minimatch": "^9.0.1",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0",
"path-scurry": "^1.10.1"
"jackspeak": "^4.0.1",
"minimatch": "^10.0.0",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^2.0.0"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=16 || 14 >=14.17"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -356,28 +348,25 @@
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/jackspeak": {
"version": "2.3.6",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz",
"integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==",
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.2.tgz",
"integrity": "sha512-bZsjR/iRjl1Nk1UkjGpAzLNfQtzuijhn2g+pbZb98HQ1Gk8vM9hfbxeMBP+M2/UUdwj0RqGG3mlvk2MsAqwvEw==",
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"engines": {
"node": ">=14"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/lru-cache": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.0.1.tgz",
"integrity": "sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==",
"version": "11.0.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.1.tgz",
"integrity": "sha512-CgeuL5uom6j/ZVrg7G/+1IXqRY8JXX4Hghfy5YE0EhoYQWvndP1kufu58cmZLNIDKnRhZrXfdS9urVWx98AipQ==",
"engines": {
"node": "14 || >=16.14"
"node": "20 || >=22"
}
},
"node_modules/make-error": {
@@ -387,23 +376,23 @@
"dev": true
},
"node_modules/minimatch": {
"version": "9.0.3",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz",
"integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==",
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/minipass": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz",
"integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==",
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"engines": {
"node": ">=16 || 14 >=14.17"
}
@@ -413,6 +402,11 @@
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
"integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw=="
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -422,32 +416,33 @@
}
},
"node_modules/path-scurry": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz",
"integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==",
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
"dependencies": {
"lru-cache": "^9.1.1 || ^10.0.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
"lru-cache": "^11.0.0",
"minipass": "^7.1.2"
},
"engines": {
"node": ">=16 || 14 >=14.17"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf": {
"version": "5.0.5",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-5.0.5.tgz",
"integrity": "sha512-CqDakW+hMe/Bz202FPEymy68P+G50RfMQK+Qo5YUqc9SPipvbGjCGKd0RSKEelbsfQuw3g5NZDSrlZZAJurH1A==",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
"integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==",
"dependencies": {
"glob": "^10.3.7"
"glob": "^11.0.0",
"package-json-from-dist": "^1.0.0"
},
"bin": {
"rimraf": "dist/esm/bin.mjs"
},
"engines": {
"node": ">=14"
"node": "20 || >=22"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
@@ -615,9 +610,9 @@
}
},
"node_modules/typescript": {
"version": "5.4.3",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.4.3.tgz",
"integrity": "sha512-KrPd3PKaCLr78MalgiwJnA25Nm8HAmdwN3mYUYZgG/wizIo9EainNVQI9/yDavtVFRN2h3k8uf3GLHuhDMgEHg==",
"version": "5.6.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.2.tgz",
"integrity": "sha512-NW8ByodCSNCwZeghjN3o+JX5OFH0Ojg6sadjEKY4huZ52TqbJTJnDo5+Tw98lSy63NZvi4n+ez5m2u5d4PkZyw==",
"dev": true,
"bin": {
"tsc": "bin/tsc",
@@ -628,9 +623,9 @@
}
},
"node_modules/undici-types": {
"version": "5.26.5",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
"integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
"version": "6.19.8",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz",
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
"dev": true
},
"node_modules/v8-compile-cache-lib": {
@@ -738,15 +733,15 @@
}
},
"node_modules/ws": {
"version": "8.11.0",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.11.0.tgz",
"integrity": "sha512-HPG3wQd9sNQoT9xHyNCXoDUa+Xw/VevmY9FoHyQ+g+rrMn4j6FB4np7Z0OhdTgjx6MgQLK7jwSy1YecU1+4Asg==",
"version": "8.17.1",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": "^5.0.2"
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
@@ -758,9 +753,9 @@
}
},
"node_modules/xmlhttprequest-ssl": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.0.0.tgz",
"integrity": "sha512-QKxVRxiRACQcVuQEYFsI1hhkrMlrXHPegbbd1yn9UHOmRxY+si12nQYzri3vbzt8VdTTRviqcKxcyllFas5z2A==",
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/xmlhttprequest-ssl/-/xmlhttprequest-ssl-2.1.1.tgz",
"integrity": "sha512-ptjR8YSJIXoA3Mbv5po7RtSYHO6mZr8s7i5VGmEk7QY2pQWyT1o0N+W1gKbOyJPUCGXGnuw0wqe8f0L6Y0ny7g==",
"engines": {
"node": ">=0.4.0"
}

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/client",
"version": "1.3.5",
"version": "1.3.6",
"description": "",
"main": "dist/packages/client/src/index.js",
"scripts": {
@@ -13,14 +13,14 @@
"license": "ISC",
"devDependencies": {
"@types/ip": "^1.1.3",
"@types/node": "^20.11.30",
"@types/node": "^22.7.4",
"ts-node": "^10.9.2",
"typescript": "^5.4.3"
"typescript": "^5.6.2"
},
"dependencies": {
"@scrypted/types": "^0.3.27",
"engine.io-client": "^6.5.3",
"follow-redirects": "^1.15.6",
"rimraf": "^5.0.5"
"@scrypted/types": "^0.3.60",
"engine.io-client": "^6.6.1",
"follow-redirects": "^1.15.9",
"rimraf": "^6.0.1"
}
}

View File

@@ -57,9 +57,9 @@ export type ScryptedClientConnectionType = 'http' | 'webrtc' | 'http-direct';
export interface ScryptedClientStatic extends ScryptedStatic {
userId?: string;
username?: string;
admin: boolean;
disconnect(): void;
onClose?: Function;
version: string;
rtcConnectionManagement?: RTCConnectionManagement;
browserSignalingSession?: BrowserSignalingSession;
address?: string;
@@ -163,11 +163,13 @@ export async function loginScryptedClient(options: ScryptedLoginOptions) {
token: body.token as string,
addresses: body.addresses as string[],
externalAddresses: body.externalAddresses as string[],
hostname: body.hostname,
// the cloud plugin will include this header.
// should maybe move this into the cloud server itself.
scryptedCloud: response.headers.get('x-scrypted-cloud') === 'true',
directAddress: response.headers.get('x-scrypted-direct-address'),
cloudAddress: response.headers.get('x-scrypted-cloud-address'),
serverId: response.headers.get('x-scrypted-server-id'),
};
}
@@ -212,6 +214,7 @@ export async function checkScryptedClientLogin(options?: ScryptedConnectionOptio
scryptedCloud: response.headers.get('x-scrypted-cloud') === 'true',
directAddress: response.headers.get('x-scrypted-direct-address'),
cloudAddress: response.headers.get('x-scrypted-cloud-address'),
serverId: response.headers.get('x-scrypted-server-id'),
};
}
@@ -225,6 +228,8 @@ export interface ScryptedClientLoginResult {
scryptedCloud: boolean;
directAddress: string;
cloudAddress: string;
hostname: string;
serverId: string;
}
export class ScryptedClientLoginError extends Error {
@@ -270,7 +275,9 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
let scryptedCloud: boolean;
let directAddress: string;
let cloudAddress: string;
let hostname: string;
let token: string;
let serverId: string;
console.log('@scrypted/client', packageJson.version);
@@ -295,6 +302,8 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
authorization = loginResult.authorization;
queryToken = loginResult.queryToken;
token = loginResult.token;
hostname = loginResult.hostname;
serverId = loginResult.serverId;
console.log('login result', Date.now() - start, loginResult);
}
else {
@@ -367,6 +376,8 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
authorization = loginCheck.authorization;
queryToken = loginCheck.queryToken;
token = loginCheck.token;
hostname = loginCheck.hostname;
serverId = loginCheck.serverId;
console.log('login checked', Date.now() - start, loginCheck);
}
@@ -518,7 +529,7 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
serializer.sendMessage(message, reject, serializationContext);
}
catch (e) {
reject?.(e);
reject?.(e as Error);
}
});
@@ -532,9 +543,10 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
});
serializer.setupRpcPeer(upgradingPeer);
const readyClose = new Promise<RpcPeer>((resolve, reject) => {
check.on('close', () => reject(new Error('closed')))
})
// is this an issue?
// const readyClose = new Promise<RpcPeer>((resolve, reject) => {
// check.on('close', () => reject(new Error('closed')))
// })
upgradingPeer.params['session'] = session;
@@ -565,7 +577,7 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
dcSerializer.sendMessage(message, reject, serializationContext);
}
catch (e) {
reject?.(e);
reject?.(e as Error);
pc.close();
}
});
@@ -666,7 +678,7 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
serializer.sendMessage(message, reject, serializationContext);
}
catch (e) {
reject?.(e);
reject?.(e as Error);
}
});
socket.on('message', data => {
@@ -708,16 +720,16 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
});
}
const [version, rtcConnectionManagement] = await Promise.all([
const [admin, rtcConnectionManagement] = await Promise.all([
(async () => {
let version = 'unknown';
try {
// info is
const info = await systemManager.getComponent('info');
version = await info.getVersion();
return !!info;
}
catch (e) {
}
return version;
return false;
})(),
(async () => {
let rtcConnectionManagement: RTCConnectionManagement;
@@ -734,7 +746,6 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
]);
console.log('api initialized', Date.now() - start);
console.log('api queried, version:', version);
const userDevice = Object.keys(systemManager.getSystemState())
.map(id => systemManager.getDeviceById(id))
@@ -781,7 +792,7 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
serializer.sendMessage(message, reject, serializationContext);
}
catch (e) {
reject?.(e);
reject?.(e as Error);
}
});
serializer.setupRpcPeer(clusterPeer);
@@ -846,7 +857,7 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
pluginRemoteAPI: undefined,
address,
connectionType,
version,
admin,
systemManager,
deviceManager,
endpointManager,
@@ -868,6 +879,8 @@ export async function connectScryptedClient(options: ScryptedClientOptions): Pro
queryToken,
authorization,
cloudAddress,
hostname,
serverId,
},
connectRPCObject,
fork: undefined,

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/rpc",
"version": "0.0.4",
"version": "0.0.5",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "@scrypted/rpc",
"version": "0.0.4",
"version": "0.0.5",
"license": "ISC",
"devDependencies": {
"@types/node": "^18.11.18",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/deferred",
"version": "0.0.4",
"version": "0.0.5",
"description": "",
"main": "dist/index.js",
"scripts": {

View File

@@ -1,6 +1,11 @@
<details>
<summary>Changelog</summary>
### 0.3.2
alexa: fix syncedDevices being undefined
### 0.3.1
alexa/google-home: fix potential vulnerability. do not allow local network control using cloud tokens belonging to a different user. the plugins are now locked to a specific scrypted cloud account once paired.

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/alexa",
"version": "0.3.2",
"version": "0.3.3",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@scrypted/alexa",
"version": "0.3.2",
"version": "0.3.3",
"dependencies": {
"axios": "^1.3.4",
"uuid": "^9.0.0"

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/alexa",
"version": "0.3.2",
"version": "0.3.3",
"scripts": {
"scrypted-setup-project": "scrypted-setup-project",
"prescrypted-setup-project": "scrypted-package-json",

View File

@@ -0,0 +1,82 @@
{
"CfgRuleId": 1,
"Class": "FaceDetection",
"CountInGroup": 2,
"DetectRegion": null,
"EventID": 10360,
"EventSeq": 6,
"Faces": [
{
"BoundingBox": [
1504,
2336,
1728,
2704
],
"Center": [
1616,
2520
],
"ObjectID": 94,
"ObjectType": "HumanFace",
"RelativeID": 0
}
],
"FrameSequence": 8251212,
"GroupID": 6,
"Mark": 0,
"Name": "FaceDetection",
"Object": {
"Action": "Appear",
"BoundingBox": [
1504,
2336,
1728,
2704
],
"Center": [
1616,
2520
],
"Confidence": 19,
"FrameSequence": 8251212,
"ObjectID": 94,
"ObjectType": "HumanFace",
"RelativeID": 0,
"SerialUUID": "",
"Source": 0.0,
"Speed": 0,
"SpeedTypeInternal": 0
},
"Objects": [
{
"Action": "Appear",
"BoundingBox": [
1504,
2336,
1728,
2704
],
"Center": [
1616,
2520
],
"Confidence": 19,
"FrameSequence": 8251212,
"ObjectID": 94,
"ObjectType": "HumanFace",
"RelativeID": 0,
"SerialUUID": "",
"Source": 0.0,
"Speed": 0,
"SpeedTypeInternal": 0
}
],
"PTS": 43774941350.0,
"Priority": 0,
"RuleID": 1,
"RuleId": 1,
"Source": -1280470024.0,
"UTC": 947510337,
"UTCMS": 0
}

View File

@@ -0,0 +1,62 @@
{
"Action": "Cross",
"Class": "Normal",
"CountInGroup": 1,
"DetectRegion": [
[
455,
260
],
[
3586,
260
],
[
3768,
7580
],
[
382,
7451
]
],
"Direction": "Enter",
"EventID": 10181,
"GroupID": 0,
"Name": "Rule1",
"Object": {
"Action": "Appear",
"BoundingBox": [
2856,
1280,
3880,
4880
],
"Center": [
3368,
3080
],
"Confidence": 0,
"LowerBodyColor": [
0,
0,
0,
0
],
"MainColor": [
0,
0,
0,
0
],
"ObjectID": 863,
"ObjectType": "Human",
"RelativeID": 0,
"Speed": 0
},
"PTS": 43380319830.0,
"RuleID": 2,
"Track": [],
"UTC": 1711446999,
"UTCMS": 701
}

View File

@@ -1,12 +1,12 @@
{
"name": "@scrypted/amcrest",
"version": "0.0.151",
"version": "0.0.164",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@scrypted/amcrest",
"version": "0.0.151",
"version": "0.0.164",
"license": "Apache",
"dependencies": {
"@scrypted/common": "file:../../common",

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/amcrest",
"version": "0.0.151",
"version": "0.0.164",
"description": "Amcrest Plugin for Scrypted",
"author": "Scrypted",
"license": "Apache",
@@ -27,6 +27,8 @@
"name": "Amcrest Plugin",
"type": "DeviceProvider",
"interfaces": [
"ScryptedSystemDevice",
"ScryptedDeviceCreator",
"DeviceProvider",
"DeviceCreator"
],

View File

@@ -4,103 +4,10 @@ import { parseHeaders, readBody } from '@scrypted/common/src/rtsp-server';
import contentType from 'content-type';
import { IncomingMessage } from 'http';
import { EventEmitter, Readable } from 'stream';
import { Destroyable } from '../../rtsp/src/rtsp';
import { createRtspMediaStreamOptions, Destroyable, UrlMediaStreamOptions } from '../../rtsp/src/rtsp';
import { getDeviceInfo } from './probe';
import { Point } from '@scrypted/sdk';
import { MediaStreamConfiguration, MediaStreamOptions, Point } from '@scrypted/sdk';
// Human
// {
// "Action" : "Cross",
// "Class" : "Normal",
// "CountInGroup" : 1,
// "DetectRegion" : [
// [ 455, 260 ],
// [ 3586, 260 ],
// [ 3768, 7580 ],
// [ 382, 7451 ]
// ],
// "Direction" : "Enter",
// "EventID" : 10181,
// "GroupID" : 0,
// "Name" : "Rule1",
// "Object" : {
// "Action" : "Appear",
// "BoundingBox" : [ 2856, 1280, 3880, 4880 ],
// "Center" : [ 3368, 3080 ],
// "Confidence" : 0,
// "LowerBodyColor" : [ 0, 0, 0, 0 ],
// "MainColor" : [ 0, 0, 0, 0 ],
// "ObjectID" : 863,
// "ObjectType" : "Human",
// "RelativeID" : 0,
// "Speed" : 0
// },
// "PTS" : 43380319830.0,
// "RuleID" : 2,
// "Track" : [],
// "UTC" : 1711446999,
// "UTCMS" : 701
// }
// Face
// {
// "CfgRuleId" : 1,
// "Class" : "FaceDetection",
// "CountInGroup" : 2,
// "DetectRegion" : null,
// "EventID" : 10360,
// "EventSeq" : 6,
// "Faces" : [
// {
// "BoundingBox" : [ 1504, 2336, 1728, 2704 ],
// "Center" : [ 1616, 2520 ],
// "ObjectID" : 94,
// "ObjectType" : "HumanFace",
// "RelativeID" : 0
// }
// ],
// "FrameSequence" : 8251212,
// "GroupID" : 6,
// "Mark" : 0,
// "Name" : "FaceDetection",
// "Object" : {
// "Action" : "Appear",
// "BoundingBox" : [ 1504, 2336, 1728, 2704 ],
// "Center" : [ 1616, 2520 ],
// "Confidence" : 19,
// "FrameSequence" : 8251212,
// "ObjectID" : 94,
// "ObjectType" : "HumanFace",
// "RelativeID" : 0,
// "SerialUUID" : "",
// "Source" : 0.0,
// "Speed" : 0,
// "SpeedTypeInternal" : 0
// },
// "Objects" : [
// {
// "Action" : "Appear",
// "BoundingBox" : [ 1504, 2336, 1728, 2704 ],
// "Center" : [ 1616, 2520 ],
// "Confidence" : 19,
// "FrameSequence" : 8251212,
// "ObjectID" : 94,
// "ObjectType" : "HumanFace",
// "RelativeID" : 0,
// "SerialUUID" : "",
// "Source" : 0.0,
// "Speed" : 0,
// "SpeedTypeInternal" : 0
// }
// ],
// "PTS" : 43774941350.0,
// "Priority" : 0,
// "RuleID" : 1,
// "RuleId" : 1,
// "Source" : -1280470024.0,
// "UTC" : 947510337,
// "UTCMS" : 0
// }
export interface AmcrestObjectDetails {
Action: string;
BoundingBox: Point;
@@ -174,6 +81,65 @@ async function readAmcrestMessage(client: Readable): Promise<string[]> {
}
}
function findValue(blob: string, prefix: string, key: string) {
const lines = blob.split('\n');
const value = lines.find(line => line.startsWith(`${prefix}.${key}`));
if (!value)
return;
const parts = value.split('=');
return parts[1];
}
function fromAmcrestAudioCodec(audioCodec: string) {
audioCodec = audioCodec?.trim();
if (audioCodec === 'AAC')
return 'aac';
if (audioCodec === 'G.711A')
return 'pcm_alaw';
if (audioCodec === 'G.711Mu')
return 'pcm_mulaw';
}
function toAmcrestAudioCodec(audioCodec: string) {
if (audioCodec === 'aac')
return 'AAC';
if (audioCodec === 'pcm_alaw')
return 'G.711A';
if (audioCodec === 'pcm_mulaw')
return 'G.711Mu';
}
function fromAmcrestVideoCodec(videoCodec: string) {
videoCodec = videoCodec?.trim();
if (videoCodec === 'H.264')
videoCodec = 'h264';
else if (videoCodec === 'H.265')
videoCodec = 'h265';
return videoCodec;
}
const amcrestResolutions = {
"1080P": [1920, 1080],
"720P": [1280, 720],
"D1": [704, 480],
"HD1": [352, 480],
"BCIF": [704, 240],
"2CIF": [704, 240],
"CIF": [352, 240],
"QCIF": [176, 120],
"NHD": [640, 360],
"VGA": [640, 480],
"QVGA": [320, 240]
};
function fromAmcrestResolution(resolution: string) {
const named = amcrestResolutions[resolution];
if (named)
return named;
const parts = resolution.split('x');
return [parseInt(parts[0]), parseInt(parts[1])];
}
export class AmcrestCameraClient {
credential: AuthFetchCredentialState;
@@ -233,6 +199,14 @@ export class AmcrestCameraClient {
return response.body;
}
async setWatermark(cameraNumber: number, enable: boolean) {
const response = await this.request({
url: `http://${this.ip}/cgi-bin/configManager.cgi?action=setConfig&VideoWidget[${cameraNumber - 1}].PictureTitle.EncodeBlend=${enable}`,
responseType: 'text',
});
return response.body;
}
async listenEvents(): Promise<Destroyable> {
const events = new EventEmitter();
const url = `http://${this.ip}/cgi-bin/eventManager.cgi?action=attach&codes=[All]`;
@@ -371,6 +345,7 @@ export class AmcrestCameraClient {
async unlock(): Promise<boolean> {
const response = await this.request({
// channel 1? this may fail through nvr.
url: `http://${this.ip}/cgi-bin/accessControl.cgi?action=openDoor&channel=1&UserID=101&Type=Remote`,
responseType: 'text',
});
@@ -379,9 +354,223 @@ export class AmcrestCameraClient {
async lock(): Promise<boolean> {
const response = await this.request({
// channel 1? this may fail through nvr.
url: `http://${this.ip}/cgi-bin/accessControl.cgi?action=closeDoor&channel=1&UserID=101&Type=Remote`,
responseType: 'text',
});
return response.body.includes('OK');
}
async resetMotionDetection(cameraNumber: number) {
const params = new URLSearchParams();
params.set(`MotionDetect[${cameraNumber - 1}].Enable`, 'true');
// from amcrest docs:
// basically a 22x18 binary grid.
// so a full cell block is 4194303.
// Currently, a region is divided into 18 lines and 22 blocks per line.
// A bit describes a block in the line.
// Bit = 1: motion in this block is monitored.
// Example:
// MotionDetect [0].Region [0] = 4194303 (0x3FFFFF): the 22 blocks in
// channel 0 line 0 is monitored.
// MotionDetect [0].Region [1] =0: the 22 blocks in channel 0 line 1 is
// not monitored.
// MotionDetect [0].Region [17] = 3: the left two blocks in the last line o
// channel 0 is monitored.
// there are 4 configurable motion windows, will use the first one, index 0.
// each window is 18 lines, 22 blocks per line.
// not sure what this first line is.
// table.MotionDetect[0].Level=3
// table.MotionDetect[0].MotionDetectWindow[0].Id=0
// table.MotionDetect[0].MotionDetectWindow[0].Name=Region1
// table.MotionDetect[0].MotionDetectWindow[0].Region[0]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[1]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[2]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[3]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[4]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[5]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[6]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[7]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[8]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[9]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[10]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[11]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[12]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[13]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[14]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[15]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[16]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Region[17]=4194303
// table.MotionDetect[0].MotionDetectWindow[0].Sensitive=60
// table.MotionDetect[0].MotionDetectWindow[0].Threshold=5
// doesn't seem to be able to be renamed.
params.set(`MotionDetect[${cameraNumber - 1}].MotionDetectWindow[0].Name`, 'Scrypted');
for (let i = 0; i < 18; i++) {
params.set(`MotionDetect[${cameraNumber - 1}].MotionDetectWindow[0].Region[${i}]`, '4194303');
}
params.set(`MotionDetect[${cameraNumber - 1}].MotionDetectWindow[0].Sensitive`, '60');
params.set(`MotionDetect[${cameraNumber - 1}].MotionDetectWindow[0].Threshold`, '5');
const response = await this.request({
url: `http://${this.ip}/cgi-bin/configManager.cgi?action=setConfig&${params}`,
responseType: 'text',
});
this.console.log('reset motion result', response.body);
}
async configureCodecs(cameraNumber: number, options: MediaStreamConfiguration) {
if (!options.id?.startsWith('channel'))
throw new Error('invalid id');
const capsResponse = await this.request({
url: `http://${this.ip}/cgi-bin/encode.cgi?action=getConfigCaps&channel=${cameraNumber}`,
responseType: 'text',
});
this.console.log(capsResponse.body);
const formatNumber = Math.max(0, parseInt(options.id?.substring('channel'.length)) - 1);
const format = options.id === 'channel0' ? 'MainFormat' : 'ExtraFormat';
const encode = `Encode[${cameraNumber - 1}].${format}[${formatNumber}]`;
const params = new URLSearchParams();
if (options.video?.bitrate) {
let bitrate = options?.video?.bitrate;
bitrate = Math.round(bitrate / 1000);
params.set(`${encode}.Video.BitRate`, bitrate.toString());
}
if (options.video?.codec === 'h264') {
params.set(`${encode}.Video.Compression`, 'H.264');
params.set(`${encode}.VideoEnable`, 'true');
}
if (options.video?.profile) {
let profile = 'Main';
if (options.video.profile === 'high')
profile = 'High';
else if (options.video.profile === 'baseline')
profile = 'Baseline';
params.set(`${encode}.Video.Profile`, profile);
}
if (options.video?.codec === 'h265') {
params.set(`${encode}.Video.Compression`, 'H.265');
}
if (options.video?.width && options.video?.height) {
params.set(`${encode}.Video.resolution`, `${options.video.width}x${options.video.height}`);
}
if (options.video?.fps) {
params.set(`${encode}.Video.FPS`, options.video.fps.toString());
}
if (options.video?.keyframeInterval) {
params.set(`${encode}.Video.GOP`, options.video?.keyframeInterval.toString());
}
if (options.video?.bitrateControl) {
params.set(`${encode}.Video.BitRateControl`, options.video.bitrateControl === 'constant' ? 'CBR' : 'VBR');
}
if (options.audio?.codec) {
params.set(`${encode}.Audio.Compression`, toAmcrestAudioCodec(options.audio.codec));
params.set(`${encode}.AudioEnable`, 'true');
}
// nothing else audio related seems configurable.
if ([...params.keys()].length) {
const response = await this.request({
url: `http://${this.ip}/cgi-bin/configManager.cgi?action=setConfig&${params}`,
responseType: 'text',
});
this.console.log('reconfigure result', response.body);
}
const caps = `caps[${cameraNumber - 1}].${format}[${formatNumber}]`;
const singleCaps = `caps.${format}[${formatNumber}]`;
const findCaps = (key: string) => {
const found = findValue(capsResponse.body, caps, key);
if (found)
return found;
// ad410 doesnt return a camera number if accessed directly
if (cameraNumber - 1 === 0)
return findValue(capsResponse.body, singleCaps, key);
}
const resolutions = findCaps('Video.ResolutionTypes').split(',').map(fromAmcrestResolution);
const bitrates = findCaps('Video.BitRateOptions').split(',').map(s => parseInt(s) * 1000);
const fpsMax = parseInt(findCaps('Video.FPSMax'));
const vso: MediaStreamConfiguration = {
id: options.id,
video: {},
};
vso.video.resolutions = resolutions;
vso.video.bitrateRange = [bitrates[0], bitrates[bitrates.length - 1]];
vso.video.fpsRange = [1, fpsMax];
return vso;
}
async getCodecs(cameraNumber: number): Promise<UrlMediaStreamOptions[]> {
const masResponse = await this.request({
url: `http://${this.ip}/cgi-bin/magicBox.cgi?action=getProductDefinition&name=MaxExtraStream`,
responseType: 'text',
});
const mas = masResponse.body.split('=')[1].trim();
// amcrest reports more streams than are acually available in its responses,
// so checking the max extra streams prevents usage of invalid streams.
const maxExtraStreams = parseInt(mas) || 1;
const vsos = [...Array(maxExtraStreams + 1).keys()].map(subtype => createRtspMediaStreamOptions(undefined, subtype));
const encodeResponse = await this.request({
url: `http://${this.ip}/cgi-bin/configManager.cgi?action=getConfig&name=Encode`,
responseType: 'text',
});
this.console.log(encodeResponse.body);
for (let i = 0; i < vsos.length; i++) {
const vso = vsos[i];
let encName: string;
if (i === 0) {
encName = `table.Encode[${cameraNumber - 1}].MainFormat[0]`;
}
else {
encName = `table.Encode[${cameraNumber - 1}].ExtraFormat[${i - 1}]`;
}
const videoCodec = fromAmcrestVideoCodec(findValue(encodeResponse.body, encName, 'Video.Compression'));
const audioCodec = fromAmcrestAudioCodec(findValue(encodeResponse.body, encName, 'Audio.Compression'));
if (vso.audio)
vso.audio.codec = audioCodec;
vso.video.codec = videoCodec;
const width = findValue(encodeResponse.body, encName, 'Video.Width');
const height = findValue(encodeResponse.body, encName, 'Video.Height');
if (width && height) {
vso.video.width = parseInt(width);
vso.video.height = parseInt(height);
}
const videoEnable = findValue(encodeResponse.body, encName, 'VideoEnable');
if (videoEnable?.trim() === 'false') {
this.console.warn('Video stream is disabled and should likely be enabled:', encName);
continue;
}
const encodeOptions = findValue(encodeResponse.body, encName, 'Video.BitRate');
if (!encodeOptions)
continue;
vso.video.bitrate = parseInt(encodeOptions) * 1000;
}
return vsos;
}
}

View File

@@ -0,0 +1,26 @@
import { AudioStreamConfiguration, Setting } from '@scrypted/sdk';
import { autoconfigureCodecs as ac } from '../../../common/src/autoconfigure-codecs';
import { AmcrestCameraClient } from "./amcrest-api";
export const amcrestAutoConfigureSettings: Setting = {
key: 'amcrest-autoconfigure',
type: 'html',
value: 'Amcrest autoconfiguration will configure the camera codecs and the motion sensor.',
};
export async function autoconfigureSettings(client: AmcrestCameraClient, cameraNumber: number) {
await client.setWatermark(cameraNumber, false).catch(() => { });
const audioOptions: AudioStreamConfiguration = {
codec: 'aac',
sampleRate: 8000,
};
await client.resetMotionDetection(cameraNumber).catch(() => {});
return ac(
() => client.getCodecs(cameraNumber),
options => client.configureCodecs(cameraNumber, options),
audioOptions,
);
}

View File

@@ -1,26 +1,27 @@
import { automaticallyConfigureSettings, checkPluginNeedsAutoConfigure } from "@scrypted/common/src/autoconfigure-codecs";
import { ffmpegLogInitialOutput } from '@scrypted/common/src/media-helpers';
import { readLength } from "@scrypted/common/src/read-stream";
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, Lock, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, Reboot, RequestPictureOptions, RequestRecordingStreamOptions, ResponseMediaStreamOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, Setting, VideoCameraConfiguration, VideoRecorder } from "@scrypted/sdk";
import sdk, { Camera, DeviceCreatorSettings, DeviceInformation, FFmpegInput, Intercom, Lock, MediaObject, MediaStreamOptions, ObjectDetectionTypes, ObjectDetector, ObjectsDetected, Reboot, RequestPictureOptions, RequestRecordingStreamOptions, ResponseMediaStreamOptions, ScryptedDeviceType, ScryptedInterface, ScryptedMimeTypes, ScryptedNativeId, Setting, VideoCameraConfiguration, VideoRecorder } from "@scrypted/sdk";
import child_process, { ChildProcess } from 'child_process';
import { PassThrough, Readable, Stream } from "stream";
import { OnvifIntercom } from "../../onvif/src/onvif-intercom";
import { RtspProvider, RtspSmartCamera, UrlMediaStreamOptions } from "../../rtsp/src/rtsp";
import { createRtspMediaStreamOptions, RtspProvider, RtspSmartCamera, UrlMediaStreamOptions } from "../../rtsp/src/rtsp";
import { AmcrestCameraClient, AmcrestEvent, AmcrestEventData } from "./amcrest-api";
import { amcrestAutoConfigureSettings, autoconfigureSettings } from "./amcrest-configure";
import { group } from "console";
const { mediaManager } = sdk;
const AMCREST_DOORBELL_TYPE = 'Amcrest Doorbell';
const DAHUA_DOORBELL_TYPE = 'Dahua Doorbell';
function findValue(blob: string, prefix: string, key: string) {
const lines = blob.split('\n');
const value = lines.find(line => line.startsWith(`${prefix}.${key}`));
if (!value)
return;
const parts = value.split('=');
return parts[1];
}
const rtspChannelSetting: Setting = {
subgroup: 'Advanced',
key: 'rtspChannel',
title: 'Channel Number Override',
description: "The channel number to use for snapshots and video. E.g., 1, 2, etc.",
placeholder: '1',
};
class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration, Camera, Intercom, Lock, VideoRecorder, Reboot, ObjectDetector {
eventStream: Stream;
@@ -110,48 +111,10 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
this.info = deviceInfo;
}
async setVideoStreamOptions(options: MediaStreamOptions): Promise<void> {
if (!options.id?.startsWith('channel'))
throw new Error('invalid id');
async setVideoStreamOptions(options: MediaStreamOptions) {
const channel = parseInt(this.getRtspChannel()) || 1;
const formatNumber = parseInt(options.id?.substring('channel'.length)) - 1;
const format = options.id === 'channel0' ? 'MainFormat' : 'ExtraFormat';
const encode = `Encode[${channel - 1}].${format}[${formatNumber}]`;
const params = new URLSearchParams();
if (options.video?.bitrate) {
let bitrate = options?.video?.bitrate;
if (!bitrate)
return;
bitrate = Math.round(bitrate / 1000);
params.set(`${encode}.Video.BitRate`, bitrate.toString());
}
if (options.video?.codec === 'h264') {
params.set(`${encode}.Video.Compression`, 'H.264');
}
if (options.video?.codec === 'h265') {
params.set(`${encode}.Video.Compression`, 'H.265');
}
if (options.video?.width && options.video?.height) {
params.set(`${encode}.Video.resolution`, `${options.video.width}x${options.video.height}`);
}
if (options.video?.fps) {
params.set(`${encode}.Video.FPS`, options.video.fps.toString());
if (options.video?.idrIntervalMillis) {
params.set(`${encode}.Video.GOP`, (options.video.fps * options.video?.idrIntervalMillis / 1000).toString());
}
}
if (options.video?.bitrateControl) {
params.set(`${encode}.Video.BitRateControl`, options.video.bitrateControl === 'variable' ? 'VBR' : 'CBR');
}
if (![...params.keys()].length)
return;
const response = await this.getClient().request({
url: `http://${this.getHttpAddress()}/cgi-bin/configManager.cgi?action=setConfig&${params}`,
responseType: 'text',
});
this.console.log('reconfigure result', response.body);
const client = this.getClient();
return client.configureCodecs(channel, options);
}
getClient() {
@@ -196,8 +159,9 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
}
else if (event === AmcrestEvent.MotionInfo) {
// this seems to be a motion pulse
if (this.motionDetected)
resetMotionTimeout();
if (!this.motionDetected)
this.motionDetected = true;
resetMotionTimeout();
}
else if (event === AmcrestEvent.MotionStop) {
// use resetMotionTimeout
@@ -283,6 +247,7 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
const ret = await super.getOtherSettings();
ret.push(
{
subgroup: 'Advanced',
title: 'Doorbell Type',
choices: [
'Not a Doorbell',
@@ -353,6 +318,7 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
ret.push(
{
subgroup: 'Advanced',
title: 'Two Way Audio',
value: twoWayAudio,
key: 'twoWayAudio',
@@ -369,8 +335,18 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
// },
);
return ret;
const ac = {
...automaticallyConfigureSettings,
subgroup: 'Advanced',
};
ac.type = 'button';
ret.push(ac);
ret.push({
...amcrestAutoConfigureSettings,
subgroup: 'Advanced',
});
return ret;
}
async takeSmartCameraPicture(options?: RequestPictureOptions): Promise<MediaObject> {
@@ -378,15 +354,12 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
}
async getUrlSettings() {
const rtspChannel = {
...rtspChannelSetting,
value: this.storage.getItem('rtspChannel'),
};
return [
{
key: 'rtspChannel',
title: 'Channel Number Override',
subgroup: 'Advanced',
description: "The channel number to use for snapshots and video. E.g., 1, 2, etc.",
placeholder: '1',
value: this.storage.getItem('rtspChannel'),
},
rtspChannel,
...await super.getUrlSettings(),
]
}
@@ -396,7 +369,7 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
}
createRtspMediaStreamOptions(url: string, index: number) {
const ret = super.createRtspMediaStreamOptions(url, index);
const ret = createRtspMediaStreamOptions(url, index);
ret.tool = 'scrypted';
return ret;
}
@@ -404,98 +377,38 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
async getConstructedVideoStreamOptions(): Promise<UrlMediaStreamOptions[]> {
const client = this.getClient();
if (!this.videoStreamOptions) {
this.videoStreamOptions = (async () => {
let mas: string;
if (this.videoStreamOptions)
return this.videoStreamOptions;
this.videoStreamOptions = (async () => {
const cameraNumber = parseInt(this.getRtspChannel()) || 1;
try {
let vsos: UrlMediaStreamOptions[];
try {
const response = await client.request({
url: `http://${this.getHttpAddress()}/cgi-bin/magicBox.cgi?action=getProductDefinition&name=MaxExtraStream`,
responseType: 'text',
})
mas = response.body.split('=')[1].trim();
this.storage.setItem('maxExtraStreams', mas.toString());
}
catch (e) {
this.console.error('error retrieving max extra streams', e);
mas = this.storage.getItem('maxExtraStreams');
}
const maxExtraStreams = parseInt(mas) || 1;
const channel = parseInt(this.getRtspChannel()) || 1;
const vsos = [...Array(maxExtraStreams + 1).keys()].map(subtype => this.createRtspMediaStreamOptions(`rtsp://${this.getRtspAddress()}/cam/realmonitor?channel=${channel}&subtype=${subtype}`, subtype));
try {
const capResponse = await client.request({
url: `http://${this.getHttpAddress()}/cgi-bin/encode.cgi?action=getConfigCaps&channel=0`,
responseType: 'text',
});
this.console.log(capResponse.body);
const encodeResponse = await client.request({
url: `http://${this.getHttpAddress()}/cgi-bin/configManager.cgi?action=getConfig&name=Encode`,
responseType: 'text',
});
this.console.log(encodeResponse.body);
for (let i = 0; i < vsos.length; i++) {
const vso = vsos[i];
let capName: string;
let encName: string;
if (i === 0) {
capName = `caps[${channel - 1}].MainFormat[0]`;
encName = `table.Encode[${channel - 1}].MainFormat[0]`;
}
else {
capName = `caps[${channel - 1}].ExtraFormat[${i - 1}]`;
encName = `table.Encode[${channel - 1}].ExtraFormat[${i - 1}]`;
}
const videoCodec = findValue(encodeResponse.body, encName, 'Video.Compression')
?.replace('.', '')?.toLowerCase()?.trim();
let audioCodec = findValue(encodeResponse.body, encName, 'Audio.Compression')
?.replace('.', '')?.toLowerCase()?.trim();
if (audioCodec?.includes('aac'))
audioCodec = 'aac';
else if (audioCodec?.includes('g711a'))
audioCodec = 'pcm_alaw';
else if (audioCodec?.includes('g711u'))
audioCodec = 'pcm_mulaw';
else if (audioCodec?.includes('g711'))
audioCodec = 'pcm';
if (vso.audio)
vso.audio.codec = audioCodec;
vso.video.codec = videoCodec;
const width = findValue(encodeResponse.body, encName, 'Video.Width');
const height = findValue(encodeResponse.body, encName, 'Video.Height');
if (width && height) {
vso.video.width = parseInt(width);
vso.video.height = parseInt(height);
}
const bitrateOptions = findValue(capResponse.body, capName, 'Video.BitRateOptions');
if (!bitrateOptions)
continue;
const encodeOptions = findValue(encodeResponse.body, encName, 'Video.BitRate');
if (!encodeOptions)
continue;
const [min, max] = bitrateOptions.split(',');
if (!min || !max)
continue;
vso.video.bitrate = parseInt(encodeOptions) * 1000;
vso.video.maxBitrate = parseInt(max) * 1000;
vso.video.minBitrate = parseInt(min) * 1000;
}
vsos = await client.getCodecs(cameraNumber);
this.storage.setItem('vsosJSON', JSON.stringify(vsos));
}
catch (e) {
this.console.error('error retrieving stream configurations', e);
vsos = JSON.parse(this.storage.getItem('vsosJSON')) as UrlMediaStreamOptions[];
}
for (const [index, vso] of vsos.entries()) {
vso.tool = 'scrypted';
vso.url = `rtsp://${this.getRtspAddress()}/cam/realmonitor?channel=${cameraNumber}&subtype=${index}`;
}
return vsos;
})();
}
}
catch (e) {
this.videoStreamOptions = undefined;
const vsos = [...Array(2).keys()].map(subtype => {
const ret = createRtspMediaStreamOptions(`rtsp://${this.getRtspAddress()}/cam/realmonitor?channel=${cameraNumber}&subtype=${subtype}`, subtype);
ret.tool = 'scrypted';
return ret;
});
return vsos;
}
})();
return this.videoStreamOptions;
}
@@ -534,6 +447,19 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
}
async putSetting(key: string, value: string) {
if (key === automaticallyConfigureSettings.key) {
const client = this.getClient();
autoconfigureSettings(client, parseInt(this.getRtspChannel()) || 1)
.then(() => {
this.log.a('Successfully configured settings.');
})
.catch(e => {
this.log.a('There was an error automatically configuring settings. More information can be viewed in the console.');
this.console.error('error autoconfiguring', e);
});
return;
}
if (key === 'continuousRecording') {
if (value === 'true') {
try {
@@ -575,7 +501,7 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
// not sure if this all works, since i don't actually have a doorbell.
// good luck!
const channel = this.getRtspChannel() || '1';
const channel = parseInt(this.getRtspChannel()) || 1;
const buffer = await mediaManager.convertMediaObjectToBuffer(media, ScryptedMimeTypes.FFmpegInput);
const ffmpegInput = JSON.parse(buffer.toString()) as FFmpegInput;
@@ -693,6 +619,11 @@ class AmcrestCamera extends RtspSmartCamera implements VideoCameraConfiguration,
}
class AmcrestProvider extends RtspProvider {
constructor(nativeId?: ScryptedNativeId) {
super(nativeId);
checkPluginNeedsAutoConfigure(this);
}
getAdditionalInterfaces() {
return [
ScryptedInterface.Reboot,
@@ -703,6 +634,9 @@ class AmcrestProvider extends RtspProvider {
];
}
getScryptedDeviceCreator(): string {
return 'Amcrest Camera';
}
async createDevice(settings: DeviceCreatorSettings, nativeId?: string): Promise<string> {
const httpAddress = `${settings.ip}:${settings.httpPort || 80}`;
@@ -712,8 +646,14 @@ class AmcrestProvider extends RtspProvider {
const password = settings.password?.toString();
const skipValidate = settings.skipValidate?.toString() === 'true';
let twoWayAudio: string;
const api = new AmcrestCameraClient(httpAddress, username, password, this.console);
if (settings.autoconfigure) {
const cameraNumber = parseInt(settings.rtspChannel as string) || 1;
await autoconfigureSettings(api, cameraNumber);
}
if (!skipValidate) {
const api = new AmcrestCameraClient(httpAddress, username, password, this.console);
try {
const deviceInfo = await api.getDeviceInfo();
@@ -744,8 +684,10 @@ class AmcrestProvider extends RtspProvider {
device.info = info;
device.putSetting('username', username);
device.putSetting('password', password);
device.setIPAddress(settings.ip?.toString());
if (settings.rtspChannel)
device.putSetting('rtspChannel', settings.rtspChannel as string);
device.setHttpPortOverride(settings.httpPort?.toString());
device.setIPAddress(settings.ip?.toString());
if (twoWayAudio)
device.putSetting('twoWayAudio', twoWayAudio);
device.updateDeviceInfo();
@@ -768,13 +710,18 @@ class AmcrestProvider extends RtspProvider {
title: 'IP Address',
placeholder: '192.168.2.222',
},
rtspChannelSetting,
{
subgroup: 'Advanced',
key: 'httpPort',
title: 'HTTP Port',
description: 'Optional: Override the HTTP Port from the default value of 80',
description: 'Optional: Override the HTTP Port from the default value of 80.',
placeholder: '80',
},
automaticallyConfigureSettings,
amcrestAutoConfigureSettings,
{
subgroup: 'Advanced',
key: 'skipValidate',
title: 'Skip Validation',
description: 'Add the device without verifying the credentials and network settings.',
@@ -786,6 +733,7 @@ class AmcrestProvider extends RtspProvider {
createCamera(nativeId: string) {
return new AmcrestCamera(nativeId, this);
}
}
export default AmcrestProvider;

View File

@@ -1,6 +1,6 @@
{
"compilerOptions": {
"module": "commonjs",
"module": "Node16",
"target": "ES2021",
"resolveJsonModule": true,
"moduleResolution": "Node16",

View File

@@ -1,4 +1,4 @@
# BTicino C300X Plugin for Scrypted
# BTicino Intercom Plugin for Scrypted
The C300X Plugin for Scrypted allows viewing your C300X intercom with incoming video/audio.

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,6 @@
{
"name": "@scrypted/bticino",
"version": "0.0.16",
"version": "0.0.18",
"scripts": {
"scrypted-setup-project": "scrypted-setup-project",
"prescrypted-setup-project": "scrypted-package-json",
@@ -20,9 +20,11 @@
"sip"
],
"scrypted": {
"name": "BTicino SIP Plugin",
"name": "BTicino Intercom Plugin",
"type": "DeviceProvider",
"interfaces": [
"ScryptedSystemDevice",
"ScryptedDeviceCreator",
"DeviceProvider",
"DeviceCreator"
],
@@ -32,14 +34,14 @@
]
},
"dependencies": {
"@scrypted/common": "file:../../common",
"@scrypted/sdk": "file:../../sdk",
"@slyoldfox/sip": "^0.0.6-1",
"sdp": "^3.0.3",
"stun": "^2.1.0"
},
"devDependencies": {
"@scrypted/common": "file:../../common",
"@scrypted/sdk": "file:../../sdk",
"@types/node": "^16.9.6",
"@types/node": "^20.11.30",
"cross-env": "^7.0.3",
"ts-node": "^10.9.1"
}

View File

@@ -4,9 +4,12 @@ import { VoicemailHandler } from "./bticino-voicemailHandler";
export class BticinoAswmSwitch extends ScryptedDeviceBase implements OnOff, HttpRequestHandler {
private timeout : NodeJS.Timeout
private voicemailHandler : VoicemailHandler
constructor(private camera: BticinoSipCamera, private voicemailHandler : VoicemailHandler) {
constructor(private camera: BticinoSipCamera) {
super( camera.nativeId + "-aswm-switch")
this.voicemailHandler = new VoicemailHandler(camera)
camera.requestHandlers.add(this.voicemailHandler)
this.timeout = setTimeout( () => this.syncStatus() , 5000 )
}
@@ -29,6 +32,7 @@ export class BticinoAswmSwitch extends ScryptedDeviceBase implements OnOff, Http
if( this.timeout ) {
clearTimeout(this.timeout)
}
this.voicemailHandler?.cancelTimer()
}
public async onRequest(request: HttpRequest, response: HttpResponse): Promise<void> {

View File

@@ -2,13 +2,12 @@ import { createBindUdp, listenZeroSingleClient } from '@scrypted/common/src/list
import { sleep } from '@scrypted/common/src/sleep';
import { RtspServer } from '@scrypted/common/src/rtsp-server';
import { addTrackControls, parseSdp } from '@scrypted/common/src/sdp-utils';
import sdk, { BinarySensor, Camera, DeviceProvider, FFmpegInput, HttpRequest, HttpRequestHandler, HttpResponse, Intercom, MediaObject, MediaStreamUrl, MotionSensor, PictureOptions, Reboot, ResponseMediaStreamOptions, ScryptedDeviceBase, ScryptedInterface, ScryptedMimeTypes, Setting, Settings, SettingValue, VideoCamera, VideoClip, VideoClipOptions, VideoClips } from '@scrypted/sdk';
import sdk, { BinarySensor, Camera, DeviceProvider, FFmpegInput, HttpRequest, HttpRequestHandler, HttpResponse, Intercom, MediaObject, MediaStreamUrl, MotionSensor, PictureOptions, Reboot, ResponseMediaStreamOptions, ScryptedDeviceBase, ScryptedMimeTypes, Setting, Settings, SettingValue, VideoCamera, VideoClip, VideoClipOptions, VideoClips } from '@scrypted/sdk';
import { SipCallSession } from '../../sip/src/sip-call-session';
import { RtpDescription, getPayloadType, getSequenceNumber, isRtpMessagePayloadType, isStunMessage } from '../../sip/src/rtp-utils';
import { VoicemailHandler } from './bticino-voicemailHandler';
import { CompositeSipMessageHandler } from '../../sip/src/compositeSipMessageHandler';
import { SipHelper } from './sip-helper';
import child_process, { ChildProcess } from 'child_process';
import child_process from 'child_process';
import { BticinoStorageSettings } from './storage-settings';
import { BticinoSipPlugin } from './main';
import { BticinoSipLock } from './bticino-lock';
@@ -29,7 +28,6 @@ import { ControllerApi } from './c300x-controller-api';
import { BticinoAswmSwitch } from './bticino-aswm-switch';
import { BticinoMuteSwitch } from './bticino-mute-switch';
const STREAM_TIMEOUT = 65000;
const { mediaManager } = sdk;
const BTICINO_CLIPS = path.join(process.env.SCRYPTED_PLUGIN_VOLUME, 'bticino-clips');
@@ -38,16 +36,14 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
private session: SipCallSession
private remoteRtpDescription: Promise<RtpDescription>
private forwarder
private refreshTimeout: NodeJS.Timeout
public requestHandlers: CompositeSipMessageHandler = new CompositeSipMessageHandler()
public incomingCallRequest : SipRequest
private settingsStorage: BticinoStorageSettings = new BticinoStorageSettings( this )
private voicemailHandler : VoicemailHandler = new VoicemailHandler(this)
private inviteHandler : InviteHandler = new InviteHandler(this)
private controllerApi : ControllerApi = new ControllerApi(this)
private muteSwitch : BticinoMuteSwitch
private aswmSwitch : BticinoAswmSwitch
private deferredCleanup
private deferredCleanup: () => void
private currentMediaObject : Promise<MediaObject>
private lastImageRefresh : number
//TODO: randomize this
@@ -60,7 +56,7 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
constructor(nativeId: string, public provider: BticinoSipPlugin) {
super(nativeId)
this.requestHandlers.add( this.voicemailHandler ).add( this.inviteHandler )
this.requestHandlers.add( this.inviteHandler )
this.persistentSipManager = new PersistentSipManager( this );
(async() => {
this.doorbellWebhookUrl = await this.doorbellWebhookEndpoint()
@@ -149,7 +145,7 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
}).on('error', (error) => {
this.console.error(error)
reject(error)
} ).end(); ;
} ).end();
});
}
@@ -283,8 +279,7 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
// get a proxy object to make sure we pass prebuffer when already watching a stream
let cam : VideoCamera = sdk.systemManager.getDeviceById<VideoCamera>(this.id)
let vs : MediaObject = await cam.getVideoStream()
let buf : Buffer = await mediaManager.convertMediaObjectToBuffer(vs, 'image/jpeg');
this.cachedImage = buf
this.cachedImage = await mediaManager.convertMediaObjectToBuffer(vs, 'image/jpeg');
this.lastImageRefresh = new Date().getTime()
this.console.log(`Camera picture updated and cached: ${this.lastImageRefresh} + cache time: ${thumbnailCacheTime} < ${now}`)
@@ -349,19 +344,13 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
this.forwarder = undefined
}
resetStreamTimeout() {
this.log.d('starting/refreshing stream')
clearTimeout(this.refreshTimeout)
this.refreshTimeout = setTimeout(() => this.stopSession(), STREAM_TIMEOUT)
}
hasActiveCall() {
return this.session;
}
stopSession() {
if (this.session) {
this.log.d('ending sip session')
this.console.log('ending sip session')
this.session.stop()
this.session = undefined
}
@@ -406,7 +395,7 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
if (this.session === sip)
this.session = undefined
try {
this.log.d('cleanup(): stopping sip session.')
this.console.log('cleanup(): stopping sip session.')
sip?.stop()
this.currentMediaObject = undefined
}
@@ -479,7 +468,7 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
this.session = sip
videoSplitter.server.on('message', (message, rinfo) => {
videoSplitter.server.on('message', (message:Buffer) => {
if ( !isStunMessage(message)) {
const isRtpMessage = isRtpMessagePayloadType(getPayloadType(message));
if (!isRtpMessage)
@@ -498,7 +487,7 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
}
});
audioSplitter.server.on('message', (message, rinfo ) => {
audioSplitter.server.on('message', (message:Buffer) => {
if ( !isStunMessage(message)) {
const isRtpMessage = isRtpMessagePayloadType(getPayloadType(message));
if (!isRtpMessage)
@@ -617,13 +606,17 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
async getDevice(nativeId: string) : Promise<any> {
if( nativeId && nativeId.endsWith('-aswm-switch')) {
this.aswmSwitch = new BticinoAswmSwitch(this, this.voicemailHandler)
this.aswmSwitch = new BticinoAswmSwitch(this)
this.aswmSwitch.info = this.info
return this.aswmSwitch
} else if( nativeId && nativeId.endsWith('-mute-switch') ) {
this.muteSwitch = new BticinoMuteSwitch(this)
this.muteSwitch.info = this.info
return this.muteSwitch
}
return new BticinoSipLock(this)
const lock = new BticinoSipLock(this)
lock.info = this.info
return lock
}
async releaseDevice(id: string, nativeId: string): Promise<void> {
@@ -633,7 +626,6 @@ export class BticinoSipCamera extends ScryptedDeviceBase implements MotionSensor
this.muteSwitch.cancelTimer()
} else {
this.stopIntercom()
this.voicemailHandler.cancelTimer()
this.persistentSipManager.cancelTimer()
this.controllerApi.cancelTimer()
}

Some files were not shown because too many files have changed in this diff Show More