mirror of
https://github.com/kerberos-io/agent.git
synced 2026-03-18 02:39:02 +00:00
Compare commits
22 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b67a72ba9a | ||
|
|
8fc9bc264d | ||
|
|
b2589f498d | ||
|
|
b1ff5134f2 | ||
|
|
3551d02d50 | ||
|
|
4c413012a4 | ||
|
|
74ea2f6cdd | ||
|
|
2a7d9b62d4 | ||
|
|
21d81b94dd | ||
|
|
091662ff26 | ||
|
|
803e8f55ef | ||
|
|
14d38ecf08 | ||
|
|
34d945055b | ||
|
|
8c44da8233 | ||
|
|
a8b79947ef | ||
|
|
7c653f809d | ||
|
|
49f1603f40 | ||
|
|
b4369ea932 | ||
|
|
83ba7baa4b | ||
|
|
9339ae30fd | ||
|
|
c18f2bd445 | ||
|
|
319876bbb0 |
@@ -30,7 +30,7 @@ Kerberos Agent is an isolated and scalable video (surveillance) management agent
|
||||
|
||||
- An IP camera which supports a RTSP H264 or H265 encoded stream,
|
||||
- (or) a USB camera, Raspberry Pi camera or other camera, that [you can transform to a valid RTSP H264 or H265 stream](https://github.com/kerberos-io/camera-to-rtsp).
|
||||
- Any hardware (ARMv6, ARMv7, ARM64, AMD) that can run a binary or container, for example: a Raspberry Pi, NVidia Jetson, Intel NUC, a VM, Bare metal machine or a full blown Kubernetes cluster.
|
||||
- Any hardware (ARMv6, ARMv7, ARM64, AMD64) that can run a binary or container, for example: a Raspberry Pi, NVidia Jetson, Intel NUC, a VM, Bare metal machine or a full blown Kubernetes cluster.
|
||||
|
||||
## :video_camera: Is my camera working?
|
||||
|
||||
@@ -109,7 +109,7 @@ This repository contains everything you'll need to know about our core product,
|
||||
|
||||
- Low memory and CPU usage.
|
||||
- Simplified and modern user interface.
|
||||
- Multi architecture (ARMv7, ARMv8, amd64, etc).).
|
||||
- Multi architecture (ARMv6, ARMv7, ARM64, AMD64)
|
||||
- Multi stream, for example recording in H265, live streaming and motion detection in H264.
|
||||
- Multi camera support: IP Cameras (H264 and H265), USB cameras and Raspberry Pi Cameras [through a RTSP proxy](https://github.com/kerberos-io/camera-to-rtsp).
|
||||
- Single camera per instance (e.g. one container per camera).
|
||||
@@ -222,6 +222,7 @@ Next to attaching the configuration file, it is also possible to override the co
|
||||
| `AGENT_MQTT_USERNAME` | Username of the MQTT broker. | "" |
|
||||
| `AGENT_MQTT_PASSWORD` | Password of the MQTT broker. | "" |
|
||||
| `AGENT_STUN_URI` | When using WebRTC, you'll need to provide a STUN server. | "stun:turn.kerberos.io:8443" |
|
||||
| `AGENT_FORCE_TURN` | Force using a TURN server, by generating relay candidates only. | "false" |
|
||||
| `AGENT_TURN_URI` | When using WebRTC, you'll need to provide a TURN server. | "turn:turn.kerberos.io:8443" |
|
||||
| `AGENT_TURN_USERNAME` | TURN username used for WebRTC. | "username1" |
|
||||
| `AGENT_TURN_PASSWORD` | TURN password used for WebRTC. | "password1" |
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
"mqtt_username": "",
|
||||
"mqtt_password": "",
|
||||
"stunuri": "stun:turn.kerberos.io:8443",
|
||||
"turn_force": "false",
|
||||
"turnuri": "turn:turn.kerberos.io:8443",
|
||||
"turn_username": "username1",
|
||||
"turn_password": "password1",
|
||||
|
||||
@@ -9,8 +9,8 @@ go 1.20
|
||||
require (
|
||||
github.com/InVisionApp/conjungo v1.1.0
|
||||
github.com/appleboy/gin-jwt/v2 v2.9.1
|
||||
github.com/bluenviron/gortsplib/v4 v4.6.3
|
||||
github.com/bluenviron/mediacommon v1.7.0
|
||||
github.com/bluenviron/gortsplib/v4 v4.7.1
|
||||
github.com/bluenviron/mediacommon v1.7.1
|
||||
github.com/cedricve/go-onvif v0.0.0-20200222191200-567e8ce298f6
|
||||
github.com/dropbox/dropbox-sdk-go-unofficial/v6 v6.0.5
|
||||
github.com/eclipse/paho.mqtt.golang v1.4.3
|
||||
@@ -36,9 +36,9 @@ require (
|
||||
github.com/swaggo/swag v1.16.2
|
||||
github.com/tevino/abool v1.2.0
|
||||
github.com/yapingcat/gomedia v0.0.0-20240106100545-1b855b02fa0d
|
||||
github.com/zaf/g711 v0.0.0-20240103222607-9fe83013ade9
|
||||
github.com/zaf/g711 v1.4.0
|
||||
go.mongodb.org/mongo-driver v1.13.1
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.58.1
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.59.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
|
||||
@@ -71,7 +71,7 @@ require (
|
||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||
github.com/go-openapi/jsonpointer v0.20.2 // indirect
|
||||
github.com/go-openapi/jsonreference v0.20.4 // indirect
|
||||
github.com/go-openapi/spec v0.20.13 // indirect
|
||||
github.com/go-openapi/spec v0.20.14 // indirect
|
||||
github.com/go-openapi/swag v0.22.7 // indirect
|
||||
github.com/go-playground/locales v0.14.1 // indirect
|
||||
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||
@@ -105,7 +105,7 @@ require (
|
||||
github.com/philhofer/fwd v1.1.2 // indirect
|
||||
github.com/pion/datachannel v1.5.5 // indirect
|
||||
github.com/pion/dtls/v2 v2.2.9 // indirect
|
||||
github.com/pion/ice/v2 v2.3.11 // indirect
|
||||
github.com/pion/ice/v2 v2.3.12 // indirect
|
||||
github.com/pion/interceptor v0.1.25 // indirect
|
||||
github.com/pion/logging v0.2.2 // indirect
|
||||
github.com/pion/mdns v0.0.9 // indirect
|
||||
@@ -136,10 +136,10 @@ require (
|
||||
go4.org/intern v0.0.0-20230525184215-6c62f75575cb // indirect
|
||||
go4.org/unsafe/assume-no-moving-gc v0.0.0-20231121144256-b99613f794b6 // indirect
|
||||
golang.org/x/arch v0.7.0 // indirect
|
||||
golang.org/x/crypto v0.17.0 // indirect
|
||||
golang.org/x/crypto v0.18.0 // indirect
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/oauth2 v0.15.0 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/oauth2 v0.16.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
|
||||
@@ -64,10 +64,10 @@ github.com/appleboy/gofight/v2 v2.1.2 h1:VOy3jow4vIK8BRQJoC/I9muxyYlJ2yb9ht2hZoS
|
||||
github.com/appleboy/gofight/v2 v2.1.2/go.mod h1:frW+U1QZEdDgixycTj4CygQ48yLTUhplt43+Wczp3rw=
|
||||
github.com/beevik/etree v1.3.0 h1:hQTc+pylzIKDb23yYprodCWWTt+ojFfUZyzU09a/hmU=
|
||||
github.com/beevik/etree v1.3.0/go.mod h1:aiPf89g/1k3AShMVAzriilpcE4R/Vuor90y83zVZWFc=
|
||||
github.com/bluenviron/gortsplib/v4 v4.6.3 h1:/FgUhxe/DGFkmwHNGNnw7NhcuZeSwnxCzYHDbyAtMjo=
|
||||
github.com/bluenviron/gortsplib/v4 v4.6.3/go.mod h1:UqdkRR5YvKHP/wHEQQySJFKJm6tIZcftdP7cNszIZ1g=
|
||||
github.com/bluenviron/mediacommon v1.7.0 h1:1j+mSw+oHDG6zXjv/tE8xxWR3G8yheMxqx76k9wJ0dE=
|
||||
github.com/bluenviron/mediacommon v1.7.0/go.mod h1:Ij/kE1LEucSjryNBVTyPL/gBI0d6/Css3f5PyrM957w=
|
||||
github.com/bluenviron/gortsplib/v4 v4.7.1 h1:ZiPHjnIsdPDfPGZgfBr2n2xCFZlvmc/5zEqdoJUa1vU=
|
||||
github.com/bluenviron/gortsplib/v4 v4.7.1/go.mod h1:3+IYh85PgIPLHr4D5z7GnRvpu/ogSHMDhsYW/CjrD8E=
|
||||
github.com/bluenviron/mediacommon v1.7.1 h1:7Lm2b8M9gUk3Ben1w+OPwadAeYseIBscwgdiL+aLtfw=
|
||||
github.com/bluenviron/mediacommon v1.7.1/go.mod h1:Ij/kE1LEucSjryNBVTyPL/gBI0d6/Css3f5PyrM957w=
|
||||
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||
github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM=
|
||||
github.com/bytedance/sonic v1.10.2 h1:GQebETVBxYB7JGWJtLBi07OVzWwt+8dWA00gEVW2ZFE=
|
||||
@@ -151,8 +151,8 @@ github.com/go-openapi/jsonpointer v0.20.2 h1:mQc3nmndL8ZBzStEo3JYF8wzmeWffDH4VbX
|
||||
github.com/go-openapi/jsonpointer v0.20.2/go.mod h1:bHen+N0u1KEO3YlmqOjTT9Adn1RfD91Ar825/PuiRVs=
|
||||
github.com/go-openapi/jsonreference v0.20.4 h1:bKlDxQxQJgwpUSgOENiMPzCTBVuc7vTdXSSgNeAhojU=
|
||||
github.com/go-openapi/jsonreference v0.20.4/go.mod h1:5pZJyJP2MnYCpoeoMAql78cCHauHj0V9Lhc506VOpw4=
|
||||
github.com/go-openapi/spec v0.20.13 h1:XJDIN+dLH6vqXgafnl5SUIMnzaChQ6QTo0/UPMbkIaE=
|
||||
github.com/go-openapi/spec v0.20.13/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw=
|
||||
github.com/go-openapi/spec v0.20.14 h1:7CBlRnw+mtjFGlPDRZmAMnq35cRzI91xj03HVyUi/Do=
|
||||
github.com/go-openapi/spec v0.20.14/go.mod h1:8EOhTpBoFiask8rrgwbLC3zmJfz4zsCUueRuPM6GNkw=
|
||||
github.com/go-openapi/swag v0.22.7 h1:JWrc1uc/P9cSomxfnsFSVWoE1FW6bNbrVPmpQYpCcR8=
|
||||
github.com/go-openapi/swag v0.22.7/go.mod h1:Gl91UqO+btAM0plGGxHqJcQZ1ZTy6jbmridBTsDy8A0=
|
||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||
@@ -356,8 +356,9 @@ github.com/pion/datachannel v1.5.5/go.mod h1:iMz+lECmfdCMqFRhXhcA/219B0SQlbpoR2V
|
||||
github.com/pion/dtls/v2 v2.2.7/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||
github.com/pion/dtls/v2 v2.2.9 h1:K+D/aVf9/REahQvqk6G5JavdrD8W1PWDKC11UlwN7ts=
|
||||
github.com/pion/dtls/v2 v2.2.9/go.mod h1:8WiMkebSHFD0T+dIU+UeBaoV7kDhOW5oDCzZ7WZ/F9s=
|
||||
github.com/pion/ice/v2 v2.3.11 h1:rZjVmUwyT55cmN8ySMpL7rsS8KYsJERsrxJLLxpKhdw=
|
||||
github.com/pion/ice/v2 v2.3.11/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E=
|
||||
github.com/pion/ice/v2 v2.3.12 h1:NWKW2b3+oSZS3klbQMIEWQ0i52Kuo0KBg505a5kQv4s=
|
||||
github.com/pion/ice/v2 v2.3.12/go.mod h1:hPcLC3kxMa+JGRzMHqQzjoSj3xtE9F+eoncmXLlCL4E=
|
||||
github.com/pion/interceptor v0.1.25 h1:pwY9r7P6ToQ3+IF0bajN0xmk/fNw/suTgaTdlwTDmhc=
|
||||
github.com/pion/interceptor v0.1.25/go.mod h1:wkbPYAak5zKsfpVDYMtEfWEy8D4zL+rpxCxPImLOg3Y=
|
||||
github.com/pion/logging v0.2.2 h1:M9+AIj/+pxNsDfAT64+MAVgJO0rsyLnoJKCqf//DoeY=
|
||||
@@ -481,8 +482,8 @@ github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/zaf/g711 v0.0.0-20240103222607-9fe83013ade9 h1:Fm9BWdkpn+ABEQJJlWjYvKQMhbuOuPGpXLlQDApD0mg=
|
||||
github.com/zaf/g711 v0.0.0-20240103222607-9fe83013ade9/go.mod h1:eCDXt3dSp/kYYAoooba7ukD/Q75jvAaS4WOMr0l1Roo=
|
||||
github.com/zaf/g711 v1.4.0 h1:XZYkjjiAg9QTBnHqEg37m2I9q3IIDv5JRYXs2N8ma7c=
|
||||
github.com/zaf/g711 v1.4.0/go.mod h1:eCDXt3dSp/kYYAoooba7ukD/Q75jvAaS4WOMr0l1Roo=
|
||||
github.com/ziutek/mymysql v1.5.4 h1:GB0qdRGsTwQSBVYuVShFBKaXSnSnYYC2d9knnE1LHFs=
|
||||
github.com/ziutek/mymysql v1.5.4/go.mod h1:LMSpPZ6DbqWFxNCHW77HeMg9I646SAhApZ/wKdgO/C0=
|
||||
go.mongodb.org/mongo-driver v1.13.1 h1:YIc7HTYsKndGK4RFzJ3covLz1byri52x0IoMB0Pt/vk=
|
||||
@@ -522,8 +523,8 @@ golang.org/x/crypto v0.10.0/go.mod h1:o4eNf7Ede1fv+hwOwZsTHl9EsPFO6q6ZvYR8vYfY45
|
||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||
golang.org/x/crypto v0.12.0/go.mod h1:NF0Gs7EO5K4qLn+Ylc+fih8BSTeIjAP05siRnAh98yw=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.17.0 h1:r8bRNjWL3GshPW3gkd+RpvzWrZAwPS49OmTGZ/uhM4k=
|
||||
golang.org/x/crypto v0.17.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
|
||||
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
@@ -605,16 +606,16 @@ golang.org/x/net v0.11.0/go.mod h1:2L/ixqYpgIVXmeoSA/4Lu7BzTG4KIyPIryS4IsOd1oQ=
|
||||
golang.org/x/net v0.13.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||
golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
|
||||
golang.org/x/oauth2 v0.15.0 h1:s8pnnxNVzjWyrvYdFUQq5llS1PX2zhPXmccZv99h7uQ=
|
||||
golang.org/x/oauth2 v0.15.0/go.mod h1:q48ptWNTY5XWf+JNten23lcvHpLJ0ZSxF5ttTHKVCAM=
|
||||
golang.org/x/oauth2 v0.16.0 h1:aDkGMBSYxElaoP81NpoUoz2oo2R2wHdZpGToUxfyQrQ=
|
||||
golang.org/x/oauth2 v0.16.0/go.mod h1:hqZ+0LWXsiVoZpeld6jVt06P3adbS2Uu911W1SsJv2o=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
@@ -862,8 +863,8 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
|
||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.58.1 h1:zhVNyN5V9G7LVuDh44q3wkcbQwtjIsmmUCieayojNYo=
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.58.1/go.mod h1:SmnEjjV9ZQr4MWRSUYEpoPyNtmtRK5J6UuJdAma+Yxw=
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.59.0 h1:W1Bfpc5+m6UdQeZDJg7GczerO2m9KmDw93yGOefRU2c=
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.59.0/go.mod h1:7zSfmC8eQQ/37+e5ID+gBX7v+MUa+1XgN6HzxLNF0mo=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
|
||||
@@ -25,7 +25,6 @@ import (
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format/rtph265"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format/rtplpcm"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format/rtpmpeg4audio"
|
||||
"github.com/bluenviron/gortsplib/v4/pkg/format/rtpsimpleaudio"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/h264"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/h265"
|
||||
"github.com/bluenviron/mediacommon/pkg/codecs/mpeg4audio"
|
||||
@@ -63,7 +62,7 @@ type Golibrtsp struct {
|
||||
AudioG711Index int8
|
||||
AudioG711Media *description.Media
|
||||
AudioG711Forma *format.G711
|
||||
AudioG711Decoder *rtpsimpleaudio.Decoder
|
||||
AudioG711Decoder *rtplpcm.Decoder
|
||||
|
||||
HasBackChannel bool
|
||||
AudioG711IndexBackChannel int8
|
||||
@@ -497,10 +496,18 @@ func (g *Golibrtsp) Start(ctx context.Context, streamType string, queue *packets
|
||||
if errSPS == nil {
|
||||
// Get width
|
||||
g.Streams[g.VideoH264Index].Width = sps.Width()
|
||||
configuration.Config.Capture.IPCamera.Width = sps.Width()
|
||||
if streamType == "main" {
|
||||
configuration.Config.Capture.IPCamera.Width = sps.Width()
|
||||
} else if streamType == "sub" {
|
||||
configuration.Config.Capture.IPCamera.SubWidth = sps.Width()
|
||||
}
|
||||
// Get height
|
||||
g.Streams[g.VideoH264Index].Height = sps.Height()
|
||||
configuration.Config.Capture.IPCamera.Height = sps.Height()
|
||||
if streamType == "main" {
|
||||
configuration.Config.Capture.IPCamera.Height = sps.Height()
|
||||
} else if streamType == "sub" {
|
||||
configuration.Config.Capture.IPCamera.SubHeight = sps.Height()
|
||||
}
|
||||
// Get FPS
|
||||
g.Streams[g.VideoH264Index].FPS = sps.FPS()
|
||||
g.VideoH264Forma.SPS = nalu
|
||||
@@ -71,6 +71,10 @@ func HandleRecordStream(queue *packets.Queue, configDirectory string, configurat
|
||||
startRecording := now
|
||||
timestamp := now
|
||||
|
||||
if config.FriendlyName != "" {
|
||||
config.Name = config.FriendlyName
|
||||
}
|
||||
|
||||
// For continuous and motion based recording we will use a single file.
|
||||
var file *os.File
|
||||
|
||||
@@ -619,7 +623,9 @@ func Base64Image(captureDevice *Capture, communication *models.Communication) st
|
||||
|
||||
// We'll try to have a keyframe, if not we'll return an empty string.
|
||||
var encodedImage string
|
||||
for {
|
||||
// Try for 3 times in a row.
|
||||
count := 0
|
||||
for count < 3 {
|
||||
if queue != nil && cursor != nil && rtspClient != nil {
|
||||
pkt, err := cursor.ReadPacket()
|
||||
if err == nil {
|
||||
@@ -632,8 +638,10 @@ func Base64Image(captureDevice *Capture, communication *models.Communication) st
|
||||
bytes, _ := utils.ImageToBytes(&img)
|
||||
encodedImage = base64.StdEncoding.EncodeToString(bytes)
|
||||
break
|
||||
} else {
|
||||
count++
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
} else {
|
||||
break
|
||||
@@ -660,15 +668,22 @@ func JpegImage(captureDevice *Capture, communication *models.Communication) imag
|
||||
|
||||
// We'll try to have a keyframe, if not we'll return an empty string.
|
||||
var image image.YCbCr
|
||||
for {
|
||||
// Try for 3 times in a row.
|
||||
count := 0
|
||||
for count < 3 {
|
||||
if queue != nil && cursor != nil && rtspClient != nil {
|
||||
pkt, err := cursor.ReadPacket()
|
||||
if err == nil {
|
||||
if !pkt.IsKeyFrame {
|
||||
continue
|
||||
}
|
||||
image, _ = (*rtspClient).DecodePacket(pkt)
|
||||
break
|
||||
image, err = (*rtspClient).DecodePacket(pkt)
|
||||
if err != nil {
|
||||
count++
|
||||
continue
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
break
|
||||
|
||||
@@ -395,6 +395,16 @@ loop:
|
||||
hasBackChannel = "true"
|
||||
}
|
||||
|
||||
hub_encryption := "false"
|
||||
if config.HubEncryption == "true" {
|
||||
hub_encryption = "true"
|
||||
}
|
||||
|
||||
e2e_encryption := "false"
|
||||
if config.Encryption != nil && config.Encryption.Enabled == "true" {
|
||||
e2e_encryption = "true"
|
||||
}
|
||||
|
||||
// We will formated the uptime to a human readable format
|
||||
// this will be used on Kerberos Hub: Uptime -> 1 day and 2 hours.
|
||||
uptimeFormatted := uptimeStart.Format("2006-01-02 15:04:05")
|
||||
@@ -411,6 +421,8 @@ loop:
|
||||
|
||||
var object = fmt.Sprintf(`{
|
||||
"key" : "%s",
|
||||
"hub_encryption": "%s",
|
||||
"e2e_encryption": "%s",
|
||||
"version" : "3.0.0",
|
||||
"release" : "%s",
|
||||
"cpuid" : "%s",
|
||||
@@ -447,12 +459,11 @@ loop:
|
||||
"docker" : true,
|
||||
"kios" : false,
|
||||
"raspberrypi" : false
|
||||
}`, config.Key, system.Version, system.CPUId, username, key, name, isEnterprise, system.Hostname, system.Architecture, system.TotalMemory, system.UsedMemory, system.FreeMemory, system.ProcessUsedMemory, macs, ips, "0", "0", "0", uptimeString, boottimeString, config.HubSite, onvifEnabled, onvifZoom, onvifPanTilt, onvifPresets, onvifPresetsList, onvifEventsList, cameraConnected, hasBackChannel)
|
||||
}`, config.Key, hub_encryption, e2e_encryption, system.Version, system.CPUId, username, key, name, isEnterprise, system.Hostname, system.Architecture, system.TotalMemory, system.UsedMemory, system.FreeMemory, system.ProcessUsedMemory, macs, ips, "0", "0", "0", uptimeString, boottimeString, config.HubSite, onvifEnabled, onvifZoom, onvifPanTilt, onvifPresets, onvifPresetsList, onvifEventsList, cameraConnected, hasBackChannel)
|
||||
|
||||
// Get the private key to encrypt the data using symmetric encryption: AES.
|
||||
HubEncryption := config.HubEncryption
|
||||
privateKey := config.HubPrivateKey
|
||||
if HubEncryption == "true" && privateKey != "" {
|
||||
if hub_encryption == "true" && privateKey != "" {
|
||||
// Encrypt the data using AES.
|
||||
encrypted, err := encryption.AesEncrypt([]byte(object), privateKey)
|
||||
if err != nil {
|
||||
|
||||
@@ -188,7 +188,7 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
||||
time.Sleep(time.Second * 3)
|
||||
return status
|
||||
}
|
||||
log.Log.Info("components.Kerberos.RunAgent(): opened RTSP sub stream: " + rtspUrl)
|
||||
log.Log.Info("components.Kerberos.RunAgent(): opened RTSP sub stream: " + subRtspUrl)
|
||||
|
||||
// Get the video streams from the RTSP server.
|
||||
videoSubStreams, err = rtspSubClient.GetVideoStreams()
|
||||
@@ -206,42 +206,8 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
||||
height := videoSubStream.Height
|
||||
|
||||
// Set config values as well
|
||||
configuration.Config.Capture.IPCamera.Width = width
|
||||
configuration.Config.Capture.IPCamera.Height = height
|
||||
}
|
||||
|
||||
if cameraSettings.RTSP != rtspUrl ||
|
||||
cameraSettings.SubRTSP != subRtspUrl ||
|
||||
cameraSettings.Width != width ||
|
||||
cameraSettings.Height != height {
|
||||
|
||||
// TODO: this condition is used to reset the decoder when the camera settings change.
|
||||
// The main idea is that you only set the decoder once, and then reuse it on each restart (no new memory allocation).
|
||||
// However the stream settings of the camera might have been changed, and so the decoder might need to be reloaded.
|
||||
// .... Not used for the moment ....
|
||||
|
||||
if cameraSettings.RTSP != "" && cameraSettings.SubRTSP != "" && cameraSettings.Initialized {
|
||||
//decoder.Close()
|
||||
//if subStreamEnabled {
|
||||
// subDecoder.Close()
|
||||
//}
|
||||
}
|
||||
|
||||
// At some routines we will need to decode the image.
|
||||
// Make sure its properly locked as we only have a single decoder.
|
||||
log.Log.Info("components.Kerberos.RunAgent(): camera settings changed, reloading decoder")
|
||||
//capture.GetVideoDecoder(decoder, streams)
|
||||
//if subStreamEnabled {
|
||||
// capture.GetVideoDecoder(subDecoder, subStreams)
|
||||
//}
|
||||
|
||||
cameraSettings.RTSP = rtspUrl
|
||||
cameraSettings.SubRTSP = subRtspUrl
|
||||
cameraSettings.Width = width
|
||||
cameraSettings.Height = height
|
||||
cameraSettings.Initialized = true
|
||||
} else {
|
||||
log.Log.Info("components.Kerberos.RunAgent(): camera settings did not change, keeping decoder")
|
||||
configuration.Config.Capture.IPCamera.SubWidth = width
|
||||
configuration.Config.Capture.IPCamera.SubHeight = height
|
||||
}
|
||||
|
||||
// We are creating a queue to store the RTSP frames in, these frames will be
|
||||
@@ -348,9 +314,20 @@ func RunAgent(configDirectory string, configuration *models.Configuration, commu
|
||||
|
||||
// Here we are cleaning up everything!
|
||||
if configuration.Config.Offline != "true" {
|
||||
communication.HandleUpload <- "stop"
|
||||
select {
|
||||
case communication.HandleUpload <- "stop":
|
||||
log.Log.Info("components.Kerberos.RunAgent(): stopping upload")
|
||||
case <-time.After(1 * time.Second):
|
||||
log.Log.Info("components.Kerberos.RunAgent(): stopping upload timed out")
|
||||
}
|
||||
}
|
||||
|
||||
select {
|
||||
case communication.HandleStream <- "stop":
|
||||
log.Log.Info("components.Kerberos.RunAgent(): stopping stream")
|
||||
case <-time.After(1 * time.Second):
|
||||
log.Log.Info("components.Kerberos.RunAgent(): stopping stream timed out")
|
||||
}
|
||||
communication.HandleStream <- "stop"
|
||||
// We use the steam channel to stop both main and sub stream.
|
||||
//if subStreamEnabled {
|
||||
// communication.HandleSubStream <- "stop"
|
||||
@@ -442,8 +419,12 @@ func ControlAgent(communication *models.Communication) {
|
||||
// After 15 seconds without activity this is thrown..
|
||||
if occurence == 3 {
|
||||
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking mainstream.")
|
||||
communication.HandleBootstrap <- "restart"
|
||||
time.Sleep(2 * time.Second)
|
||||
select {
|
||||
case communication.HandleBootstrap <- "restart":
|
||||
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking substream.")
|
||||
case <-time.After(1 * time.Second):
|
||||
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking substream timed out")
|
||||
}
|
||||
occurence = 0
|
||||
}
|
||||
|
||||
@@ -464,9 +445,12 @@ func ControlAgent(communication *models.Communication) {
|
||||
|
||||
// After 15 seconds without activity this is thrown..
|
||||
if occurenceSub == 3 {
|
||||
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking substream.")
|
||||
communication.HandleBootstrap <- "restart"
|
||||
time.Sleep(2 * time.Second)
|
||||
select {
|
||||
case communication.HandleBootstrap <- "restart":
|
||||
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking substream.")
|
||||
case <-time.After(1 * time.Second):
|
||||
log.Log.Info("components.Kerberos.ControlAgent(): Restarting machinery because of blocking substream timed out")
|
||||
}
|
||||
occurenceSub = 0
|
||||
}
|
||||
}
|
||||
@@ -603,7 +587,12 @@ func GetDays(c *gin.Context, configDirectory string, configuration *models.Confi
|
||||
// @Success 200 {object} models.APIResponse
|
||||
func StopAgent(c *gin.Context, communication *models.Communication) {
|
||||
log.Log.Info("components.Kerberos.StopAgent(): sending signal to stop agent, this will os.Exit(0).")
|
||||
communication.HandleBootstrap <- "stop"
|
||||
select {
|
||||
case communication.HandleBootstrap <- "stop":
|
||||
log.Log.Info("components.Kerberos.StopAgent(): Stopping machinery.")
|
||||
case <-time.After(1 * time.Second):
|
||||
log.Log.Info("components.Kerberos.StopAgent(): Stopping machinery timed out")
|
||||
}
|
||||
c.JSON(200, gin.H{
|
||||
"stopped": true,
|
||||
})
|
||||
@@ -618,7 +607,12 @@ func StopAgent(c *gin.Context, communication *models.Communication) {
|
||||
// @Success 200 {object} models.APIResponse
|
||||
func RestartAgent(c *gin.Context, communication *models.Communication) {
|
||||
log.Log.Info("components.Kerberos.RestartAgent(): sending signal to restart agent.")
|
||||
communication.HandleBootstrap <- "restart"
|
||||
select {
|
||||
case communication.HandleBootstrap <- "restart":
|
||||
log.Log.Info("components.Kerberos.RestartAgent(): Restarting machinery.")
|
||||
case <-time.After(1 * time.Second):
|
||||
log.Log.Info("components.Kerberos.RestartAgent(): Restarting machinery timed out")
|
||||
}
|
||||
c.JSON(200, gin.H{
|
||||
"restarted": true,
|
||||
})
|
||||
|
||||
@@ -386,6 +386,9 @@ func OverrideWithEnvironmentVariables(configuration *models.Configuration) {
|
||||
case "AGENT_STUN_URI":
|
||||
configuration.Config.STUNURI = value
|
||||
break
|
||||
case "AGENT_FORCE_TURN":
|
||||
configuration.Config.ForceTurn = value
|
||||
break
|
||||
case "AGENT_TURN_URI":
|
||||
configuration.Config.TURNURI = value
|
||||
break
|
||||
@@ -485,7 +488,9 @@ func SaveConfig(configDirectory string, config models.Config, configuration *mod
|
||||
if communication.CameraConnected {
|
||||
select {
|
||||
case communication.HandleBootstrap <- "restart":
|
||||
default:
|
||||
log.Log.Info("config.main.SaveConfig(): update config, restart agent.")
|
||||
case <-time.After(1 * time.Second):
|
||||
log.Log.Info("config.main.SaveConfig(): update config, restart agent.")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ func ConfigureLogrus(level string, output string, timezone *time.Location) {
|
||||
logLevel = logrus.ErrorLevel
|
||||
} else if level == "debug" {
|
||||
logLevel = logrus.DebugLevel
|
||||
logrus.SetReportCaller(true)
|
||||
} else if level == "fatal" {
|
||||
logLevel = logrus.FatalLevel
|
||||
} else if level == "warning" {
|
||||
|
||||
@@ -33,6 +33,7 @@ type Config struct {
|
||||
MQTTUsername string `json:"mqtt_username" bson:"mqtt_username"`
|
||||
MQTTPassword string `json:"mqtt_password" bson:"mqtt_password"`
|
||||
STUNURI string `json:"stunuri" bson:"stunuri"`
|
||||
ForceTurn string `json:"turn_force" bson:"turn_force"`
|
||||
TURNURI string `json:"turnuri" bson:"turnuri"`
|
||||
TURNUsername string `json:"turn_username" bson:"turn_username"`
|
||||
TURNPassword string `json:"turn_password" bson:"turn_password"`
|
||||
@@ -72,11 +73,14 @@ type Capture struct {
|
||||
// IPCamera configuration, such as the RTSP url of the IPCamera and the FPS.
|
||||
// Also includes ONVIF integration
|
||||
type IPCamera struct {
|
||||
RTSP string `json:"rtsp"`
|
||||
Width int `json:"width"`
|
||||
Height int `json:"height"`
|
||||
FPS string `json:"fps"`
|
||||
RTSP string `json:"rtsp"`
|
||||
SubRTSP string `json:"sub_rtsp"`
|
||||
SubWidth int `json:"sub_width"`
|
||||
SubHeight int `json:"sub_height"`
|
||||
SubFPS string `json:"sub_fps"`
|
||||
ONVIF string `json:"onvif,omitempty" bson:"onvif"`
|
||||
ONVIFXAddr string `json:"onvif_xaddr" bson:"onvif_xaddr"`
|
||||
ONVIFUsername string `json:"onvif_username" bson:"onvif_username"`
|
||||
|
||||
@@ -27,31 +27,13 @@ func PackageMQTTMessage(configuration *Configuration, msg Message) ([]byte, erro
|
||||
msg.DeviceId = msg.Payload.DeviceId
|
||||
msg.Timestamp = time.Now().Unix()
|
||||
|
||||
// We'll hide the message (by default in latest version)
|
||||
// We will encrypt using the Kerberos Hub private key if set.
|
||||
/*msg.Hidden = false
|
||||
if configuration.Config.HubPrivateKey != "" {
|
||||
msg.Hidden = true
|
||||
pload := msg.Payload
|
||||
// Pload to base64
|
||||
data, err := json.Marshal(pload)
|
||||
if err != nil {
|
||||
msg.Hidden = false
|
||||
} else {
|
||||
k := configuration.Config.Encryption.SymmetricKey
|
||||
encryptedValue, err := encryption.AesEncrypt(data, k)
|
||||
if err == nil {
|
||||
data := base64.StdEncoding.EncodeToString(encryptedValue)
|
||||
msg.Payload.HiddenValue = data
|
||||
msg.Payload.Value = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
}*/
|
||||
// Configuration
|
||||
config := configuration.Config
|
||||
|
||||
// Next to hiding the message, we can also encrypt it using your own private key.
|
||||
// Which is not stored in a remote environment (hence you are the only one owning it).
|
||||
msg.Encrypted = false
|
||||
if configuration.Config.Encryption != nil && configuration.Config.Encryption.Enabled == "true" {
|
||||
if config.Encryption != nil && config.Encryption.Enabled == "true" {
|
||||
msg.Encrypted = true
|
||||
}
|
||||
msg.PublicKey = ""
|
||||
@@ -85,19 +67,47 @@ func PackageMQTTMessage(configuration *Configuration, msg Message) ([]byte, erro
|
||||
rsaKey, _ := key.(*rsa.PrivateKey)
|
||||
|
||||
// Create a 16bit key random
|
||||
k := configuration.Config.Encryption.SymmetricKey
|
||||
if config.Encryption != nil && config.Encryption.SymmetricKey != "" {
|
||||
k := config.Encryption.SymmetricKey
|
||||
encryptedValue, err := encryption.AesEncrypt(data, k)
|
||||
if err == nil {
|
||||
|
||||
data := base64.StdEncoding.EncodeToString(encryptedValue)
|
||||
// Sign the encrypted value
|
||||
signature, err := encryption.SignWithPrivateKey([]byte(data), rsaKey)
|
||||
if err == nil {
|
||||
base64Signature := base64.StdEncoding.EncodeToString(signature)
|
||||
msg.Payload.EncryptedValue = data
|
||||
msg.Payload.Signature = base64Signature
|
||||
msg.Payload.Value = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// We'll hide the message (by default in latest version)
|
||||
// We will encrypt using the Kerberos Hub private key if set.
|
||||
msg.Hidden = false
|
||||
if config.HubEncryption == "true" && config.HubPrivateKey != "" {
|
||||
msg.Hidden = true
|
||||
}
|
||||
|
||||
if msg.Hidden {
|
||||
pload := msg.Payload
|
||||
// Pload to base64
|
||||
data, err := json.Marshal(pload)
|
||||
if err != nil {
|
||||
msg.Hidden = false
|
||||
} else {
|
||||
k := config.HubPrivateKey
|
||||
encryptedValue, err := encryption.AesEncrypt(data, k)
|
||||
if err == nil {
|
||||
|
||||
data := base64.StdEncoding.EncodeToString(encryptedValue)
|
||||
// Sign the encrypted value
|
||||
signature, err := encryption.SignWithPrivateKey([]byte(data), rsaKey)
|
||||
if err == nil {
|
||||
base64Signature := base64.StdEncoding.EncodeToString(signature)
|
||||
msg.Payload.EncryptedValue = data
|
||||
msg.Payload.Signature = base64Signature
|
||||
msg.Payload.Value = make(map[string]interface{})
|
||||
}
|
||||
msg.Payload.HiddenValue = data
|
||||
msg.Payload.EncryptedValue = ""
|
||||
msg.Payload.Signature = ""
|
||||
msg.Payload.Value = make(map[string]interface{})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1104,7 +1104,9 @@ func GetEventMessages(dev *onvif.Device, pullPointAddress string) ([]ONVIFEvents
|
||||
|
||||
for _, message := range pullMessagesResponse.NotificationMessage {
|
||||
log.Log.Debug("onvif.main.GetEventMessages(pullMessages): " + string(message.Topic.TopicKinds))
|
||||
log.Log.Debug("onvif.main.GetEventMessages(pullMessages): " + string(message.Message.Message.Data.SimpleItem[0].Name) + " " + string(message.Message.Message.Data.SimpleItem[0].Value))
|
||||
if len(message.Message.Message.Data.SimpleItem) > 0 {
|
||||
log.Log.Debug("onvif.main.GetEventMessages(pullMessages): " + string(message.Message.Message.Data.SimpleItem[0].Name) + " " + string(message.Message.Message.Data.SimpleItem[0].Value))
|
||||
}
|
||||
if message.Topic.TopicKinds == "tns1:Device/Trigger/Relay" {
|
||||
if len(message.Message.Message.Data.SimpleItem) > 0 {
|
||||
if message.Message.Message.Data.SimpleItem[0].Name == "LogicalState" {
|
||||
|
||||
@@ -166,9 +166,33 @@ func MQTTListenerHandler(mqttClient mqtt.Client, hubKey string, configDirectory
|
||||
|
||||
// We will receive all messages from our hub, so we'll need to filter to the relevant device.
|
||||
if message.Mid != "" && message.Timestamp != 0 && message.DeviceId == configuration.Config.Key {
|
||||
// Messages might be encrypted, if so we'll
|
||||
// need to decrypt them.
|
||||
var payload models.Payload
|
||||
|
||||
// Messages might be hidden, if so we'll need to decrypt them using the Kerberos Hub private key.
|
||||
if message.Hidden && configuration.Config.HubEncryption == "true" {
|
||||
hiddenValue := message.Payload.HiddenValue
|
||||
if len(hiddenValue) > 0 {
|
||||
privateKey := configuration.Config.HubPrivateKey
|
||||
if privateKey != "" {
|
||||
data, err := base64.StdEncoding.DecodeString(hiddenValue)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
visibleValue, err := encryption.AesDecrypt(data, privateKey)
|
||||
if err != nil {
|
||||
log.Log.Error("routers.mqtt.main.MQTTListenerHandler(): error decrypting message: " + err.Error())
|
||||
return
|
||||
}
|
||||
json.Unmarshal(visibleValue, &payload)
|
||||
message.Payload = payload
|
||||
} else {
|
||||
log.Log.Error("routers.mqtt.main.MQTTListenerHandler(): error decrypting message, no private key provided.")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Messages might be end-to-end encrypted, if so we'll need to decrypt them,
|
||||
// using our own keys.
|
||||
if message.Encrypted && configuration.Config.Encryption != nil && configuration.Config.Encryption.Enabled == "true" {
|
||||
encryptedValue := message.Payload.EncryptedValue
|
||||
if len(encryptedValue) > 0 {
|
||||
@@ -352,16 +376,26 @@ func HandleRequestConfig(mqttClient mqtt.Client, hubKey string, payload models.P
|
||||
json.Unmarshal(jsonData, &configPayload)
|
||||
|
||||
if configPayload.Timestamp != 0 {
|
||||
// Get Config from the device
|
||||
|
||||
// Get Config from the device
|
||||
key := configuration.Config.Key
|
||||
name := configuration.Config.Name
|
||||
if configuration.Config.FriendlyName != "" {
|
||||
name = configuration.Config.FriendlyName
|
||||
}
|
||||
|
||||
if key != "" && name != "" {
|
||||
|
||||
// Copy the config, as we don't want to share the encryption part.
|
||||
deepCopy := configuration.Config
|
||||
|
||||
// We need a fix for the width and height if a substream.
|
||||
// The ROI requires the width and height of the sub stream.
|
||||
if configuration.Config.Capture.IPCamera.SubRTSP != "" {
|
||||
deepCopy.Capture.IPCamera.Width = configuration.Config.Capture.IPCamera.SubWidth
|
||||
deepCopy.Capture.IPCamera.Height = configuration.Config.Capture.IPCamera.SubHeight
|
||||
}
|
||||
|
||||
var configMap map[string]interface{}
|
||||
inrec, _ := json.Marshal(deepCopy)
|
||||
json.Unmarshal(inrec, &configMap)
|
||||
|
||||
@@ -161,6 +161,8 @@ logreader:
|
||||
if err == nil {
|
||||
bytes, _ := utils.ImageToBytes(&img)
|
||||
encodedImage = base64.StdEncoding.EncodeToString(bytes)
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else {
|
||||
log.Log.Error("routers.websocket.main.ForwardSDStream():" + err.Error())
|
||||
|
||||
@@ -135,6 +135,11 @@ func InitializeWebRTCConnection(configuration *models.Configuration, communicati
|
||||
|
||||
api := pionWebRTC.NewAPI(pionWebRTC.WithMediaEngine(mediaEngine))
|
||||
|
||||
policy := pionWebRTC.ICETransportPolicyAll
|
||||
if config.ForceTurn == "true" {
|
||||
policy = pionWebRTC.ICETransportPolicyRelay
|
||||
}
|
||||
|
||||
peerConnection, err := api.NewPeerConnection(
|
||||
pionWebRTC.Configuration{
|
||||
ICEServers: []pionWebRTC.ICEServer{
|
||||
@@ -147,7 +152,7 @@ func InitializeWebRTCConnection(configuration *models.Configuration, communicati
|
||||
Credential: w.TurnServersCredential,
|
||||
},
|
||||
},
|
||||
//ICETransportPolicy: pionWebRTC.ICETransportPolicyRelay, // This will force a relay server, we might make this configurable.
|
||||
ICETransportPolicy: policy,
|
||||
},
|
||||
)
|
||||
|
||||
@@ -222,6 +227,8 @@ func InitializeWebRTCConnection(configuration *models.Configuration, communicati
|
||||
candateBinary, err := json.Marshal(candateJSON)
|
||||
if err == nil {
|
||||
valueMap["candidate"] = string(candateBinary)
|
||||
valueMap["sdp"] = []byte(base64.StdEncoding.EncodeToString([]byte(answer.SDP)))
|
||||
valueMap["session_id"] = handshake.SessionID
|
||||
} else {
|
||||
log.Log.Info("webrtc.main.InitializeWebRTCConnection(): something went wrong while marshalling candidate: " + err.Error())
|
||||
}
|
||||
@@ -250,6 +257,7 @@ func InitializeWebRTCConnection(configuration *models.Configuration, communicati
|
||||
// Create a config map
|
||||
valueMap := make(map[string]interface{})
|
||||
valueMap["sdp"] = []byte(base64.StdEncoding.EncodeToString([]byte(answer.SDP)))
|
||||
valueMap["session_id"] = handshake.SessionID
|
||||
log.Log.Info("webrtc.main.InitializeWebRTCConnection(): Send SDP answer")
|
||||
|
||||
// We'll send the candidate to the hub
|
||||
@@ -326,7 +334,8 @@ func WriteToTrack(livestreamCursor *packets.QueueCursor, configuration *models.C
|
||||
|
||||
var cursorError error
|
||||
var pkt packets.Packet
|
||||
var previousTime time.Duration
|
||||
var previousTimeVideo time.Duration
|
||||
var previousTimeAudio time.Duration
|
||||
|
||||
start := false
|
||||
receivedKeyFrame := false
|
||||
@@ -336,8 +345,6 @@ func WriteToTrack(livestreamCursor *packets.QueueCursor, configuration *models.C
|
||||
for cursorError == nil {
|
||||
|
||||
pkt, cursorError = livestreamCursor.ReadPacket()
|
||||
bufferDuration := pkt.Time - previousTime
|
||||
previousTime = pkt.Time
|
||||
|
||||
if config.Capture.ForwardWebRTC != "true" && peerConnectionCount == 0 {
|
||||
start = false
|
||||
@@ -385,6 +392,11 @@ func WriteToTrack(livestreamCursor *packets.QueueCursor, configuration *models.C
|
||||
//}
|
||||
|
||||
if pkt.IsVideo {
|
||||
|
||||
// Calculate the difference
|
||||
bufferDuration := pkt.Time - previousTimeVideo
|
||||
previousTimeVideo = pkt.Time
|
||||
|
||||
// Start at the first keyframe
|
||||
if pkt.IsKeyFrame {
|
||||
start = true
|
||||
@@ -401,8 +413,13 @@ func WriteToTrack(livestreamCursor *packets.QueueCursor, configuration *models.C
|
||||
}
|
||||
}
|
||||
} else if pkt.IsAudio {
|
||||
|
||||
// Calculate the difference
|
||||
bufferDuration := pkt.Time - previousTimeAudio
|
||||
previousTimeAudio = pkt.Time
|
||||
|
||||
// We will send the audio
|
||||
sample := pionMedia.Sample{Data: pkt.Data, Duration: pkt.Time}
|
||||
sample := pionMedia.Sample{Data: pkt.Data, Duration: bufferDuration}
|
||||
if err := audioTrack.WriteSample(sample); err != nil && err != io.ErrClosedPipe {
|
||||
log.Log.Error("webrtc.main.WriteToTrack(): something went wrong while writing sample: " + err.Error())
|
||||
}
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "Allgemeine Einstellungen für den Kerberos Agent",
|
||||
"key": "Schlüssel",
|
||||
"camera_name": "Kamera Name",
|
||||
"camera_friendly_name": "Kamera Anzeigename",
|
||||
"timezone": "Zeitzone",
|
||||
"select_timezone": "Zeitzone auswählen",
|
||||
"advanced_configuration": "Erweiterte Konfiguration",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN Server",
|
||||
"turn_username": "Benutzername",
|
||||
"turn_password": "Passwort",
|
||||
"force_turn": "Erzwinge TURN",
|
||||
"force_turn_description": "Erzwinge die Verwendung von TURN",
|
||||
"stun_turn_forward": "Weiterleiten und transkodieren",
|
||||
"stun_turn_description_forward": "Optiemierungen und Verbesserungen der TURN/STUN Kommunikation.",
|
||||
"stun_turn_webrtc": "Weiterleiten an WebRTC Schnittstelle",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "Die möglichkeit zur Speicherung der Daten an einem Zentralen Ort ist der Beginn einer effektiven Videoüberwachung. Es kann zwischen",
|
||||
"description2_persistence": ", oder einem Drittanbieter gewählt werden.",
|
||||
"select_persistence": "Speicherort auswählen",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos Hub Proxy URL",
|
||||
"kerberoshub_description_proxyurl": "Der Proxy Endpunkt zum hochladen der Aufnahmen.",
|
||||
"kerberoshub_apiurl": "Kerberos Hub API URL",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "General settings for your Kerberos Agent",
|
||||
"key": "Key",
|
||||
"camera_name": "Camera name",
|
||||
"camera_friendly_name": "Friendly name",
|
||||
"timezone": "Timezone",
|
||||
"select_timezone": "Select a timezone",
|
||||
"advanced_configuration": "Advanced configuration",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN server",
|
||||
"turn_username": "Username",
|
||||
"turn_password": "Password",
|
||||
"force_turn": "Force TURN",
|
||||
"force_turn_description": "Force TURN usage, even when STUN is available.",
|
||||
"stun_turn_forward": "Forwarding and transcoding",
|
||||
"stun_turn_description_forward": "Optimisations and enhancements for TURN/STUN communication.",
|
||||
"stun_turn_webrtc": "Forwarding to WebRTC broker",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "Having the ability to store your recordings is the beginning of everything. You can choose between our",
|
||||
"description2_persistence": ", or a 3rd party provider",
|
||||
"select_persistence": "Select a persistence",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos Hub Proxy URL",
|
||||
"kerberoshub_description_proxyurl": "The Proxy endpoint for uploading your recordings.",
|
||||
"kerberoshub_apiurl": "Kerberos Hub API URL",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "General settings for your Kerberos Agent",
|
||||
"key": "Key",
|
||||
"camera_name": "Camera name",
|
||||
"camera_friendly_name": "Camera friendly name",
|
||||
"timezone": "Timezone",
|
||||
"select_timezone": "Select a timezone",
|
||||
"advanced_configuration": "Advanced configuration",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN server",
|
||||
"turn_username": "Username",
|
||||
"turn_password": "Password",
|
||||
"force_turn": "Force TURN",
|
||||
"force_turn_description": "Force TURN usage, even when STUN is available.",
|
||||
"stun_turn_forward": "Forwarding and transcoding",
|
||||
"stun_turn_description_forward": "Optimisations and enhancements for TURN/STUN communication.",
|
||||
"stun_turn_webrtc": "Forwarding to WebRTC broker",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "Having the ability to store your recordings is the beginning of everything. You can choose between our",
|
||||
"description2_persistence": ", or a 3rd party provider",
|
||||
"select_persistence": "Select a persistence",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos Hub Proxy URL",
|
||||
"kerberoshub_description_proxyurl": "The Proxy endpoint for uploading your recordings.",
|
||||
"kerberoshub_apiurl": "Kerberos Hub API URL",
|
||||
|
||||
@@ -79,6 +79,7 @@
|
||||
"description_general": "Paramètres généraux pour votre Agent Kerberos",
|
||||
"key": "Clé",
|
||||
"camera_name": "Nom de la caméra",
|
||||
"camera_friendly_name": "Nom convivial de la caméra",
|
||||
"timezone": "Fuseau horaire",
|
||||
"select_timezone": "Sélectionner un fuseau horaire",
|
||||
"advanced_configuration": "Configuration avancée",
|
||||
@@ -144,6 +145,8 @@
|
||||
"turn_server": "Serveur TURN",
|
||||
"turn_username": "Nom d'utilisateur",
|
||||
"turn_password": "Mot de passe",
|
||||
"force_turn": "Forcer l'utilisation de TURN",
|
||||
"force_turn_description": "Forcer l'utilisation de TURN au lieu de STUN",
|
||||
"stun_turn_forward": "Redirection et transcodage",
|
||||
"stun_turn_description_forward": "Optimisations et améliorations pour la communication TURN/STUN.",
|
||||
"stun_turn_webrtc": "Redirection pour l'agent WebRTC",
|
||||
@@ -184,6 +187,8 @@
|
||||
"description_persistence": "Avoir la possibilité de stocker vos enregistrements est le commencement de tout. Vous pouvez choisir entre notre",
|
||||
"description2_persistence": " ou auprès d'un fournisseur tiers",
|
||||
"select_persistence": "Sélectionner une persistance",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "URL du proxy Kerberos Hub",
|
||||
"kerberoshub_description_proxyurl": "Le point de terminaison du proxy pour téléverser vos enregistrements.",
|
||||
"kerberoshub_apiurl": "URL de l'API Kerberos Hub",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "आपके Kerberos एजेंट के लिए सामान्य सेटिंग्स",
|
||||
"key": "की",
|
||||
"camera_name": "कैमरे का नाम",
|
||||
"camera_friendly_name": "कैमरे का नाम",
|
||||
"timezone": "समय क्षेत्र",
|
||||
"select_timezone": "समयक्षेत्र चुनें",
|
||||
"advanced_configuration": "एडवांस कॉन्फ़िगरेशन",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN server",
|
||||
"turn_username": "उपयोगकर्ता नाम",
|
||||
"turn_password": "पासवर्ड",
|
||||
"force_turn": "Force TURN",
|
||||
"force_turn_description": "Force TURN usage, even when STUN is available.",
|
||||
"stun_turn_forward": "फोरवर्डींग और ट्रांसकोडिंग",
|
||||
"stun_turn_description_forward": "TURN/STUN संचार के लिए अनुकूलन और संवर्द्धन।",
|
||||
"stun_turn_webrtc": "WebRTC ब्रोकर को फोरवर्डींग किया जा रहा है",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "अपनी रिकॉर्डिंग संग्रहीत करने की क्षमता होना हर चीज़ की शुरुआत है। ",
|
||||
"description2_persistence": ", या कोई तृतीय पक्ष प्रदाता",
|
||||
"select_persistence": "एक दृढ़ता का चयन करें",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos हब प्रॉक्सी URL",
|
||||
"kerberoshub_description_proxyurl": "आपकी रिकॉर्डिंग अपलोड करने के लिए प्रॉक्सी एंडपॉइंट।",
|
||||
"kerberoshub_apiurl": "Kerberos हब API URL",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "Impostazioni generali del Kerberos Agent",
|
||||
"key": "Chiave",
|
||||
"camera_name": "Nome videocamera",
|
||||
"camera_friendly_name": "Nome amichevole videocamera",
|
||||
"timezone": "Fuso orario",
|
||||
"select_timezone": "Seleziona un fuso orario",
|
||||
"advanced_configuration": "Configurazione avanzata",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN server",
|
||||
"turn_username": "Username",
|
||||
"turn_password": "Password",
|
||||
"force_turn": "Forza TURN",
|
||||
"force_turn_description": "Forza l'uso di TURN per lo streaming in diretta.",
|
||||
"stun_turn_forward": "Inoltro e transcodifica",
|
||||
"stun_turn_description_forward": "Ottimizzazioni e miglioramenti per la comunicazione TURN/STUN.",
|
||||
"stun_turn_webrtc": "Inoltro al broker WebRTC",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "La possibilità di poter salvare le tue registrazioni rappresenta l'inizio di tutto. Puoi scegliere tra il nostro",
|
||||
"description2_persistence": ", oppure un provider di terze parti",
|
||||
"select_persistence": "Seleziona una persistenza",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "URL Proxy Kerberos Hub",
|
||||
"kerberoshub_description_proxyurl": "Endpoint del Proxy per l'upload delle registrazioni.",
|
||||
"kerberoshub_apiurl": "API URL Kerberos Hub",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "Kerberos エージェントの一般設定",
|
||||
"key": "鍵",
|
||||
"camera_name": "カメラ名",
|
||||
"camera_friendly_name": "カメラのフレンドリー名",
|
||||
"timezone": "タイムゾーン",
|
||||
"select_timezone": "タイムゾーンを選択",
|
||||
"advanced_configuration": "詳細設定",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURNサーバー",
|
||||
"turn_username": "ユーザー名",
|
||||
"turn_password": "パスワード",
|
||||
"force_turn": "Force TURN",
|
||||
"force_turn_description": "Force TURN usage, even when STUN is available.",
|
||||
"stun_turn_forward": "転送とトランスコーディング",
|
||||
"stun_turn_description_forward": "TURN/STUN 通信の最適化と機能強化。",
|
||||
"stun_turn_webrtc": "WebRTC ブローカーへの転送",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "録音を保存する機能を持つことは、すべての始まりです。",
|
||||
"description2_persistence": "、またはサードパーティのプロバイダ",
|
||||
"select_persistence": "永続性を選択",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos ハブ プロキシ URL",
|
||||
"kerberoshub_description_proxyurl": "記録をアップロードするためのプロキシ エンドポイント。",
|
||||
"kerberoshub_apiurl": "ケルベロス ハブ API URL",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "Algemene instellingen voor jouw Kerberos Agent",
|
||||
"key": "Key",
|
||||
"camera_name": "Camera naam",
|
||||
"camera_friendly_name": "Camera vriendelijke naam",
|
||||
"timezone": "Tijdzone",
|
||||
"select_timezone": "Selecteer uw tijdzone",
|
||||
"advanced_configuration": "Geavanceerde instellingen",
|
||||
@@ -146,6 +147,8 @@
|
||||
"turn_server": "TURN server",
|
||||
"turn_username": "Gebruikersnaam",
|
||||
"turn_password": "Wachtwoord",
|
||||
"force_turn": "Verplicht TURN",
|
||||
"force_turn_description": "Verplicht TURN connectie, ook al is er een STUN connectie mogelijk.",
|
||||
"stun_turn_forward": "Doorsturen en transcoden",
|
||||
"stun_turn_description_forward": "Optimalisatie en verbetering voor TURN/STUN communicatie.",
|
||||
"stun_turn_webrtc": "Doorsturen naar een WebRTC broker",
|
||||
@@ -186,6 +189,8 @@
|
||||
"description_persistence": "De mogelijkheid om jouw opnames op te slaan is het begin van alles. Je kan kiezen tussen ons",
|
||||
"description2_persistence": ", of een 3rd party provider",
|
||||
"select_persistence": "Selecteer een opslagmethode",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos Hub Proxy URL",
|
||||
"kerberoshub_description_proxyurl": "De Proxy url voor het opladen van jouw opnames.",
|
||||
"kerberoshub_apiurl": "Kerberos Hub API URL",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "General settings for your Kerberos Agent",
|
||||
"key": "Key",
|
||||
"camera_name": "Camera name",
|
||||
"camera_friendly_name": "Camera friendly name",
|
||||
"timezone": "Timezone",
|
||||
"select_timezone": "Select a timezone",
|
||||
"advanced_configuration": "Advanced configuration",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN server",
|
||||
"turn_username": "Username",
|
||||
"turn_password": "Password",
|
||||
"force_turn": "Force TURN",
|
||||
"force_turn_description": "Force TURN usage, even when STUN is available.",
|
||||
"stun_turn_forward": "Forwarding and transcoding",
|
||||
"stun_turn_description_forward": "Optimisations and enhancements for TURN/STUN communication.",
|
||||
"stun_turn_webrtc": "Forwarding to WebRTC broker",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "Having the ability to store your recordings is the beginning of everything. You can choose between our",
|
||||
"description2_persistence": ", or a 3rd party provider",
|
||||
"select_persistence": "Select a persistence",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos Hub Proxy URL",
|
||||
"kerberoshub_description_proxyurl": "The Proxy endpoint for uploading your recordings.",
|
||||
"kerberoshub_apiurl": "Kerberos Hub API URL",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "Configurações gerais para seu agente Kerberos",
|
||||
"key": "Chave",
|
||||
"camera_name": "Nome da câmera",
|
||||
"camera_friendly_name": "Nome amigável da câmera",
|
||||
"timezone": "Fuso horário",
|
||||
"select_timezone": "Selecione a timezone",
|
||||
"advanced_configuration": "Configurações avançadas",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "Servidor TURN",
|
||||
"turn_username": "Usuario",
|
||||
"turn_password": "Senha",
|
||||
"force_turn": "Forçar TURN",
|
||||
"force_turn_description": "Forçar o uso de TURN em vez de STUN.",
|
||||
"stun_turn_forward": "Encaminhamento e transcodificação",
|
||||
"stun_turn_description_forward": "Otimizações e melhorias para a comunicação TURN/STUN.",
|
||||
"stun_turn_webrtc": "Encaminhamento para broker WebRTC",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "Ter a capacidade de armazenar suas gravações é o começo de tudo. Você pode escolher entre nossos",
|
||||
"description2_persistence": ", ou um provedor terceirizado",
|
||||
"select_persistence": "Selecione um provedor de armazenamento",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Url proxy para Kerberos Hub",
|
||||
"kerberoshub_description_proxyurl": "O endpoint Proxy para enviar suas gravações.",
|
||||
"kerberoshub_apiurl": "Url de API do Kerberos Hub",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "Общие настройки Kerberos Agent",
|
||||
"key": "Ключ",
|
||||
"camera_name": "Название камеры",
|
||||
"camera_friendly_name": "Дружественное название камеры",
|
||||
"timezone": "Часовой пояс",
|
||||
"select_timezone": "Выберите часовой пояс",
|
||||
"advanced_configuration": "Расширенные настройки",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN сервер",
|
||||
"turn_username": "Имя пользователя",
|
||||
"turn_password": "Пароль",
|
||||
"force_turn": "Force TURN",
|
||||
"force_turn_description": "Force TURN usage, even when STUN is available.",
|
||||
"stun_turn_forward": "Переадресация и транскодирование",
|
||||
"stun_turn_description_forward": "Оптимизация и усовершенствование связи TURN/STUN.",
|
||||
"stun_turn_webrtc": "Переадресация на WebRTC-брокера",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "Возможность хранения записей - это начало всего. Вы можете выбрать один из наших вариантов",
|
||||
"description2_persistence": ", или стороннего провайдера",
|
||||
"select_persistence": "Выберите хранилище",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos Hub Proxy URL",
|
||||
"kerberoshub_description_proxyurl": "Конечная точка Proxy для загрузки записей.",
|
||||
"kerberoshub_apiurl": "Kerberos Hub API URL",
|
||||
|
||||
@@ -80,6 +80,7 @@
|
||||
"description_general": "Kerberos Agent 常规设置",
|
||||
"key": "Key",
|
||||
"camera_name": "相机名称",
|
||||
"camera_friendly_name": "相机友好名称",
|
||||
"timezone": "时区",
|
||||
"select_timezone": "选择时区",
|
||||
"advanced_configuration": "高级配置",
|
||||
@@ -145,6 +146,8 @@
|
||||
"turn_server": "TURN 服务",
|
||||
"turn_username": "账户",
|
||||
"turn_password": "密码",
|
||||
"force_turn": "Force TURN",
|
||||
"force_turn_description": "Force TURN usage, even when STUN is available.",
|
||||
"stun_turn_forward": "转发和转码",
|
||||
"stun_turn_description_forward": "TURN/STUN 通信的优化和增强。",
|
||||
"stun_turn_webrtc": "转发到 WebRTC 代理",
|
||||
@@ -185,6 +188,8 @@
|
||||
"description_persistence": "能够存储您的录像是一切的开始。您可以在我们的",
|
||||
"description2_persistence": ", 或第三方提供商之间进行选择。",
|
||||
"select_persistence": "选择持久化存储",
|
||||
"kerberoshub_encryption": "Encryption",
|
||||
"kerberoshub_encryption_description": "All traffic from/to Kerberos Hub will encrypted using AES-256.",
|
||||
"kerberoshub_proxyurl": "Kerberos Hub 代理 URL",
|
||||
"kerberoshub_description_proxyurl": "用于上传您录像的代理端点",
|
||||
"kerberoshub_apiurl": "Kerberos Hub API URL",
|
||||
|
||||
@@ -100,7 +100,7 @@ class App extends React.Component {
|
||||
</div>
|
||||
)}
|
||||
<div id="page-root">
|
||||
<Sidebar logo={logo} title="Kerberos Agent" version="v3.1.1" mobile>
|
||||
<Sidebar logo={logo} title="Kerberos Agent" version="v3.1.8" mobile>
|
||||
<Profilebar
|
||||
username={username}
|
||||
email="support@kerberos.io"
|
||||
|
||||
@@ -824,6 +824,15 @@ class Settings extends React.Component {
|
||||
}
|
||||
/>
|
||||
|
||||
<Input
|
||||
noPadding
|
||||
label={t('settings.overview.camera_friendly_name')}
|
||||
defaultValue={config.friendly_name}
|
||||
onChange={(value) =>
|
||||
this.onUpdateField('', 'friendly_name', value, config)
|
||||
}
|
||||
/>
|
||||
|
||||
<Dropdown
|
||||
isRadio
|
||||
icon="world"
|
||||
@@ -1088,6 +1097,20 @@ class Settings extends React.Component {
|
||||
this.onUpdateField('', 'turn_password', value, config)
|
||||
}
|
||||
/>
|
||||
<br />
|
||||
<div className="toggle-wrapper">
|
||||
<Toggle
|
||||
on={config.turn_force === 'true'}
|
||||
disabled={false}
|
||||
onClick={(event) =>
|
||||
this.onUpdateToggle('', 'turn_force', event, config)
|
||||
}
|
||||
/>
|
||||
<div>
|
||||
<span>{t('settings.streaming.force_turn')}</span>
|
||||
<p>{t('settings.streaming.force_turn_description')}</p>
|
||||
</div>
|
||||
</div>
|
||||
</BlockBody>
|
||||
<BlockFooter>
|
||||
<Button
|
||||
@@ -1129,7 +1152,8 @@ class Settings extends React.Component {
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
noPadding
|
||||
type="password"
|
||||
iconright="activity"
|
||||
label={t('settings.persistence.kerberoshub_publickey')}
|
||||
placeholder={t(
|
||||
'settings.persistence.kerberoshub_description_publickey'
|
||||
@@ -1140,7 +1164,8 @@ class Settings extends React.Component {
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
noPadding
|
||||
type="password"
|
||||
iconright="activity"
|
||||
label={t('settings.persistence.kerberoshub_privatekey')}
|
||||
placeholder={t(
|
||||
'settings.persistence.kerberoshub_description_privatekey'
|
||||
@@ -1161,6 +1186,27 @@ class Settings extends React.Component {
|
||||
this.onUpdateField('', 'hub_site', value, config)
|
||||
}
|
||||
/>
|
||||
|
||||
<br />
|
||||
<div className="toggle-wrapper">
|
||||
<Toggle
|
||||
on={config.hub_encryption === 'true'}
|
||||
disabled={false}
|
||||
onClick={(event) =>
|
||||
this.onUpdateToggle('', 'hub_encryption', event, config)
|
||||
}
|
||||
/>
|
||||
<div>
|
||||
<span>
|
||||
{t('settings.persistence.kerberoshub_encryption')}
|
||||
</span>
|
||||
<p>
|
||||
{t(
|
||||
'settings.persistence.kerberoshub_encryption_description'
|
||||
)}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</BlockBody>
|
||||
<BlockFooter>
|
||||
<Button
|
||||
@@ -1336,7 +1382,8 @@ class Settings extends React.Component {
|
||||
</div>
|
||||
|
||||
<Input
|
||||
noPadding
|
||||
type="password"
|
||||
iconright="activity"
|
||||
label={t('settings.overview.encryption_fingerprint')}
|
||||
value={config.encryption.fingerprint}
|
||||
onChange={(value) =>
|
||||
@@ -1349,7 +1396,8 @@ class Settings extends React.Component {
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
noPadding
|
||||
type="password"
|
||||
iconright="activity"
|
||||
label={t('settings.overview.encryption_privatekey')}
|
||||
value={config.encryption.private_key}
|
||||
onChange={(value) =>
|
||||
@@ -1362,7 +1410,8 @@ class Settings extends React.Component {
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
noPadding
|
||||
type="password"
|
||||
iconright="activity"
|
||||
label={t('settings.overview.encryption_symmetrickey')}
|
||||
value={config.encryption.symmetric_key}
|
||||
onChange={(value) =>
|
||||
@@ -2296,7 +2345,8 @@ class Settings extends React.Component {
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
noPadding
|
||||
type="password"
|
||||
iconright="activity"
|
||||
label={t(
|
||||
'settings.persistence.kerberosvault_accesskey'
|
||||
)}
|
||||
@@ -2316,7 +2366,8 @@ class Settings extends React.Component {
|
||||
}
|
||||
/>
|
||||
<Input
|
||||
noPadding
|
||||
type="password"
|
||||
iconright="activity"
|
||||
label={t(
|
||||
'settings.persistence.kerberosvault_secretkey'
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user