mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-29 11:26:49 +03:00
Compare commits
12
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4e98a76464 | ||
|
|
cf19e52722 | ||
|
|
9ab0d97278 | ||
|
|
e24bb8be72 | ||
|
|
ac0f6c9dd3 | ||
|
|
56c6416556 | ||
|
|
885d6776fd | ||
|
|
27db8f1d74 | ||
|
|
51eaae4857 | ||
|
|
54ba07917d | ||
|
|
ee35be19ac | ||
|
|
605d051b3d |
@@ -5,4 +5,3 @@
|
||||
/docker/rockchip/ @MarcA711
|
||||
/docker/rocm/ @harakas
|
||||
/docker/hailo8l/ @spanner3003
|
||||
/docker/deepx/ @sixfab
|
||||
|
||||
@@ -1,131 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Installs the DEEPX NPU kernel driver and the DX-RT runtime on the Docker host,
|
||||
# then enables the vendor's dxrt.service. A container cannot load kernel
|
||||
# modules, so this runs outside the image; the driver creates the /dev/dxrt*
|
||||
# nodes and the daemon multiplexes the NPU across host and container.
|
||||
#
|
||||
# Driver, runtime and firmware versions must agree or inference hangs instead
|
||||
# of failing at startup. The set this script installs is pinned in
|
||||
# driver_version, runtime_version and firmware_version below; move them
|
||||
# together, never one at a time.
|
||||
#
|
||||
# DEEPX NPU support in Frigate is maintained by Sixfab (https://sixfab.com).
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
driver_version="v2.6.0"
|
||||
# the commit the tag resolves to, since DEEPX signs neither tags nor releases
|
||||
# and this is compiled and installed as root. Update both together
|
||||
driver_commit="7074748e7104f470b02f517583abba652b3f05fa"
|
||||
firmware_version="v2.7.4"
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y git build-essential "linux-headers-$(uname -r)" pciutils wget
|
||||
|
||||
if ! lspci -d 1ff4: | grep -q .; then
|
||||
echo "No DEEPX device found on the PCIe bus (lspci -d 1ff4:)."
|
||||
echo "Check that the module is seated correctly before continuing."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# fetch the pinned commit rather than cloning the tag, so a retag cannot swap
|
||||
# in different source. The build directory is reused so a second run after a
|
||||
# failure does not stop on the directory already being there
|
||||
mkdir -p dx_rt_npu_linux_driver
|
||||
cd dx_rt_npu_linux_driver
|
||||
git init -q
|
||||
git remote get-url origin > /dev/null 2>&1 ||
|
||||
git remote add origin https://github.com/DEEPX-AI/dx_rt_npu_linux_driver.git
|
||||
git fetch --depth 1 origin "${driver_commit}"
|
||||
git checkout -q FETCH_HEAD
|
||||
|
||||
fetched_commit=$(git rev-parse HEAD)
|
||||
if [[ "${fetched_commit}" != "${driver_commit}" ]]; then
|
||||
echo "Fetched commit ${fetched_commit} does not match pinned driver_commit ${driver_commit}."
|
||||
echo "Refusing to build unverified driver source."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
cd modules
|
||||
|
||||
sudo ./build.sh -c install --reload
|
||||
|
||||
sudo depmod -A
|
||||
|
||||
# dx_dma is the PCIe transport, dxrt_driver the NPU driver on top of it
|
||||
for module in dx_dma dxrt_driver; do
|
||||
if ! sudo modprobe "${module}"; then
|
||||
echo "Unable to load the ${module} kernel module, common reasons are:"
|
||||
echo "- Secure Boot is enabled and is rejecting the unsigned module."
|
||||
echo "- The running kernel does not match the installed linux-headers."
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
if ! compgen -G "/dev/dxrt*" > /dev/null; then
|
||||
echo "Modules loaded but no /dev/dxrt* device node appeared."
|
||||
echo "Run ./sanity_check.sh from the driver repo to diagnose."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
runtime_version="v3.4.0"
|
||||
declare -A runtime_sha256=(
|
||||
[amd64]="736cfef009ce9e974ab1ab610d867239d19d72a426a53e367ddcbd53297b6e20"
|
||||
[arm64]="eb6107f5f02f2ad76ae89f414e8b5f346f34fbc6f0888236136853a26be6f6a0"
|
||||
)
|
||||
|
||||
runtime_release="${runtime_version#v}"
|
||||
deb_arch=$(dpkg --print-architecture)
|
||||
deb_file="/tmp/libdxrt-bin_${runtime_release}_${deb_arch}.deb"
|
||||
|
||||
wget -qO "${deb_file}" \
|
||||
"https://raw.githubusercontent.com/DEEPX-AI/dx_rt/${runtime_version}/release/${runtime_release}/libdxrt-bin_${runtime_release}_${deb_arch}.deb"
|
||||
|
||||
expected_sha256="${runtime_sha256[${deb_arch}]:-}"
|
||||
if [[ -z "${expected_sha256}" ]]; then
|
||||
echo "No pinned SHA-256 for architecture ${deb_arch}; refusing to install."
|
||||
exit 1
|
||||
fi
|
||||
if [[ "$(sha256sum "${deb_file}" | cut -d' ' -f1)" != "${expected_sha256}" ]]; then
|
||||
echo "SHA-256 mismatch for ${deb_file}; refusing to install."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
sudo dpkg -i "${deb_file}"
|
||||
sudo ldconfig
|
||||
rm -f "${deb_file}"
|
||||
|
||||
sudo cp /usr/share/libdxrt-bin/service/dxrt.service /etc/systemd/system/
|
||||
|
||||
# With an endpoint set, dxrtd binds that path only, so the socket goes in a
|
||||
# directory Frigate can mount (kept across restarts so the mount stays valid)
|
||||
# and a symlink at the default /tmp path keeps host tools that do not set the
|
||||
# variable working through their own fallback.
|
||||
sudo mkdir -p /etc/systemd/system/dxrt.service.d
|
||||
sudo tee /etc/systemd/system/dxrt.service.d/frigate.conf > /dev/null <<'UNIT'
|
||||
[Service]
|
||||
RuntimeDirectory=dxrt
|
||||
RuntimeDirectoryMode=0755
|
||||
RuntimeDirectoryPreserve=yes
|
||||
Environment=DXRT_DYNAMIC_IPC_ENDPOINT=/run/dxrt/dxrt_dynamic_ipc.sock
|
||||
ExecStartPost=/bin/ln -sfn /run/dxrt/dxrt_dynamic_ipc.sock /tmp/dxrt_dynamic_ipc.sock
|
||||
UNIT
|
||||
|
||||
sudo systemctl daemon-reload
|
||||
sudo systemctl enable dxrt.service
|
||||
sudo systemctl restart dxrt.service
|
||||
|
||||
if ! sudo systemctl is-active --quiet dxrt.service; then
|
||||
echo "dxrt.service did not start. Check: sudo journalctl -u dxrt.service"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "DEEPX driver and runtime installation complete."
|
||||
echo "Driver version: $(modinfo -F version dxrt_driver) (expected ${driver_version#v})"
|
||||
echo "Runtime version: ${runtime_release}"
|
||||
echo "Device node(s): $(echo /dev/dxrt*)"
|
||||
echo
|
||||
echo "This driver expects NPU firmware ${firmware_version}. Check it with:"
|
||||
echo " dxrt-cli --status"
|
||||
echo "Update the module if it does not match before starting Frigate."
|
||||
@@ -37,7 +37,6 @@ device_globs=(
|
||||
"/dev/nvmap"
|
||||
"/dev/nvidia*"
|
||||
"/dev/memx*"
|
||||
"/dev/dxrt*"
|
||||
)
|
||||
|
||||
IFS=',' read -ra extra_globs <<< "${DEVICE_ACL_PATHS:-}"
|
||||
|
||||
@@ -12,6 +12,6 @@ nvidia-cusolver-cu12==11.7.3.90; platform_machine == 'x86_64'
|
||||
nvidia-cusparse-cu12==12.5.8.93; platform_machine == 'x86_64'
|
||||
nvidia-nccl-cu12==2.26.2.post1; platform_machine == 'x86_64'
|
||||
nvidia-nvjitlink-cu12==12.8.93; platform_machine == 'x86_64'
|
||||
onnx==1.23.*; platform_machine == 'x86_64'
|
||||
onnx==1.16.*; platform_machine == 'x86_64'
|
||||
onnxruntime-gpu==1.24.*; platform_machine == 'x86_64'
|
||||
protobuf==3.20.3; platform_machine == 'x86_64'
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
onnx == 1.23.0; platform_machine == 'aarch64'
|
||||
onnx == 1.14.0; platform_machine == 'aarch64'
|
||||
protobuf == 3.20.3; platform_machine == 'aarch64'
|
||||
|
||||
@@ -967,65 +967,6 @@ memryx:
|
||||
# The .zip file must contain:
|
||||
# ├── ssdlite_mobilenet.dfp (a file ending with .dfp)
|
||||
# └── ssdlite_mobilenet_post.onnx (optional; only if the model includes a cropped post-processing network)
|
||||
deepx:
|
||||
title: DEEPX NPU
|
||||
models:
|
||||
- key: yolo
|
||||
label: YOLO
|
||||
recommended: true
|
||||
download: No model is bundled with Frigate. Download a pre-compiled YOLO `.dxnn` model from the [DEEPX ModelZoo](https://developer.deepx.ai/modelzoo) or compile your own with DX-COM, then bind-mount it into the container and point the model's `path` at it. The recommended model is `yolox-s_640x640_ppu.dxnn`. Its Post-Processing Unit (PPU) compile moves candidate selection onto the NPU, which makes it the fastest ModelZoo model measured through Frigate (about 13 ms on a DX-M1). The output layout is read from the compiled model, so anchor-based, anchor-free, NMS-in-head and PPU models (anchor-based or anchor-free) all need no extra configuration; prefer a `PPU` variant whenever the ModelZoo offers one. PPU models must be compiled with DX-COM 2.4.0 or later, which writes the head layout Frigate reads into the file.
|
||||
ui: |-
|
||||
Navigate to **Settings > System > Detection models** and select **DEEPX NPU** from the **Hardware** dropdown. Then, on the same model, open the **Custom Model** tab and configure:
|
||||
|
||||
| Field | Value |
|
||||
| ---------------------------------------- | ---------------------------------------------------- |
|
||||
| **Custom object detector model path** | `/config/model_cache/deepx/yolox-s_640x640_ppu.dxnn` |
|
||||
| **Label map for custom object detector** | `/labelmap/coco-80.txt` |
|
||||
| **Object detection model input width** | `640` |
|
||||
| **Object detection model input height** | `640` |
|
||||
| **Model Input Pixel Color Format** | `rgb` (Frigate's default value) |
|
||||
| **Model Input Tensor Shape** | `nhwc` (Frigate's default value) |
|
||||
| **Model Input D Type** | `int` (Frigate's default value) |
|
||||
| **Object Detection Model Type** | `yolo-generic` |
|
||||
|
||||
Quantization is baked into the compiled model, so no normalization is applied on the host and the input defaults do not need to be overridden.
|
||||
yaml: |-
|
||||
models:
|
||||
- devices:
|
||||
- deepx:PCIe:0
|
||||
path: /config/model_cache/deepx/yolox-s_640x640_ppu.dxnn
|
||||
labelmap_path: /labelmap/coco-80.txt
|
||||
model_type: yolo-generic
|
||||
width: 640
|
||||
height: 640
|
||||
- key: yolox
|
||||
label: YOLOX
|
||||
recommended: false
|
||||
download: No model is bundled with Frigate. Download a pre-compiled YOLOX `.dxnn` model from the [DEEPX ModelZoo](https://developer.deepx.ai/modelzoo), then bind-mount it into the container and point the model's `path` at it. The `_ppu` variant is faster and also works with the `yolo-generic` model type; the plain export needs `yolox` so its raw head is decoded.
|
||||
ui: |-
|
||||
Navigate to **Settings > System > Detection models** and select **DEEPX NPU** from the **Hardware** dropdown. Then, on the same model, open the **Custom Model** tab and configure:
|
||||
|
||||
| Field | Value |
|
||||
| ---------------------------------------- | ---------------------------------------- |
|
||||
| **Custom object detector model path** | `/config/model_cache/deepx/yolox-s_640x640.dxnn`|
|
||||
| **Label map for custom object detector** | `/labelmap/coco-80.txt` |
|
||||
| **Object detection model input width** | `640` |
|
||||
| **Object detection model input height** | `640` |
|
||||
| **Model Input Pixel Color Format** | `rgb` (Frigate's default value) |
|
||||
| **Model Input Tensor Shape** | `nhwc` (Frigate's default value) |
|
||||
| **Model Input D Type** | `int` (Frigate's default value) |
|
||||
| **Object Detection Model Type** | `yolox` |
|
||||
|
||||
The width and height must match the resolution the `.dxnn` file was compiled for.
|
||||
yaml: |-
|
||||
models:
|
||||
- devices:
|
||||
- deepx:PCIe:0
|
||||
path: /config/model_cache/deepx/yolox-s_640x640.dxnn
|
||||
labelmap_path: /labelmap/coco-80.txt
|
||||
model_type: yolox
|
||||
width: 640
|
||||
height: 640
|
||||
tensorrt:
|
||||
title: TensorRT
|
||||
models:
|
||||
|
||||
@@ -24,7 +24,6 @@ Frigate supports multiple different detectors that work on different types of ha
|
||||
- [Coral EdgeTPU](#edge-tpu-detector): The Google Coral EdgeTPU is available in USB, Mini PCIe, and m.2 formats allowing for a wide range of compatibility with devices.
|
||||
- [Hailo](#hailo): The Hailo-8, Hailo-8L and Hailo-8R AI Acceleration modules are available in m.2 format with a HAT for RPi devices, offering a wide range of compatibility with devices.
|
||||
- <CommunityBadge /> [MemryX](#memryx-mx3): The MX3 Acceleration module is available in m.2 format, offering broad compatibility across various platforms.
|
||||
- <CommunityBadge /> [DEEPX](#deepx-npu): The DEEPX NPU is available in m.2 format and as a HAT+ for the Raspberry Pi 5, offering broad compatibility across various platforms.
|
||||
|
||||
**AMD**
|
||||
|
||||
@@ -613,63 +612,6 @@ For detailed instructions on compiling models, refer to the [MemryX Compiler](ht
|
||||
|
||||
---
|
||||
|
||||
## DEEPX NPU
|
||||
|
||||
This detector is available for use with the DEEPX NPU, both the DX-M1 M.2 module and the DX-M1M on the Sixfab AI HAT+ for the Raspberry Pi 5. The configuration below applies unchanged to either form factor. DEEPX NPU support in Frigate is developed and maintained by [Sixfab](https://sixfab.com).
|
||||
|
||||
See the [installation docs](../frigate/installation.md#deepx-npu) for information on installing the DEEPX kernel driver and runtime on the host and passing the NPU through to the container.
|
||||
|
||||
To run a model on a DEEPX NPU, list a `deepx` device on that model.
|
||||
|
||||
:::info
|
||||
|
||||
The DX-RT Python bindings are not part of the Frigate image. They are downloaded and installed into `/config/.local` the first time a DEEPX device is configured, verified against pinned checksums, and updated automatically when a Frigate release pins a new version. If the container has no internet access, see [Detector runtimes](/frigate/network_requirements#detector-runtimes) for how to provide the files yourself.
|
||||
|
||||
:::
|
||||
|
||||
### Configuration {#configuration-deepx}
|
||||
|
||||
<ModelConfigDropdown detectorTitle="DEEPX" models={objectDetectorsModels.deepx.models} />
|
||||
|
||||
Frigate does not bundle a model for this detector. Models must be compiled to DEEPX's `.dxnn` format. Two model types are supported:
|
||||
|
||||
- `yolo-generic` for YOLO object detection models, the recommended default. The detector reads the model's output layout from the compiled file, so anchor-based, anchor-free and NMS-in-head models all work with the same configuration, as do models compiled with DEEPX's Post-Processing Unit (PPU) support.
|
||||
- `yolox` for YOLOX models compiled without PPU support, whose raw head needs Frigate's YOLOX decoder. A YOLOX model compiled with PPU support works under either `yolox` or `yolo-generic`.
|
||||
|
||||
The quickest way to get one is the [DEEPX ModelZoo](https://developer.deepx.ai/modelzoo), which publishes pre-compiled `.dxnn` files for a range of YOLO object detection models. Download the `.dxnn`, bind-mount it into the container, and point the model's `path` at it. Alternatively, compile your own model with the DX-COM compiler. The recommended starting point is `yolox-s_640x640_ppu.dxnn`, the fastest ModelZoo model measured through Frigate:
|
||||
|
||||
```yaml
|
||||
models:
|
||||
- devices:
|
||||
- deepx:PCIe:0
|
||||
path: /config/model_cache/deepx/yolox-s_640x640_ppu.dxnn
|
||||
labelmap_path: /labelmap/coco-80.txt
|
||||
model_type: yolo-generic
|
||||
width: 640
|
||||
height: 640
|
||||
```
|
||||
|
||||
For PPU models, use a `.dxnn` compiled with DX-COM 2.4.0 or later. Frigate reads the PPU head layout the compiler writes into the file and refuses to load a PPU model without it.
|
||||
|
||||
`model_type` must be set to `yolo-generic` or `yolox` to match the model; `yolo-generic` is the recommended default unless the model is a raw YOLOX export. Frigate defaults it to `ssd`, which this detector does not support, so the detector refuses to start on a model that leaves it unset.
|
||||
|
||||
`width` and `height` must match the resolution the model was compiled for. Quantization parameters are baked into the `.dxnn` file at compile time, so no normalization is applied on the host and Frigate's default `input_tensor`, `input_pixel_format`, and `input_dtype` values do not need to be overridden.
|
||||
|
||||
A DEEPX device is `PCIe:<index>`, as reported on the detector settings page. The NPU daemon multiplexes across processes, so the same device may be listed more than once to run additional inference processes against it:
|
||||
|
||||
```yaml
|
||||
models:
|
||||
- devices:
|
||||
- deepx:PCIe:0
|
||||
- deepx:PCIe:0
|
||||
```
|
||||
|
||||
#### Label maps
|
||||
|
||||
The object detection models in the DEEPX ModelZoo are trained on the standard 80-class COCO label set, so `labelmap_path` must be set to `/labelmap/coco-80.txt`. Frigate's default label map uses an extended 91-class COCO scheme, and leaving it in place will cause detections to be reported as the wrong object type. For `yolo-generic` models the label map is also what the detector uses to tell the output layout, so a label map with the wrong number of classes is reported as an error at startup.
|
||||
|
||||
---
|
||||
|
||||
## NVidia TensorRT Detector
|
||||
|
||||
Nvidia Jetson devices may be used for object detection using the TensorRT libraries. Due to the size of the additional libraries, this detector is only provided in images with the `-tensorrt-jp6` tag suffix, e.g. `ghcr.io/blakeblackshear/frigate:stable-tensorrt-jp6`. This detector is designed to work with Yolo models for object detection.
|
||||
|
||||
@@ -65,11 +65,6 @@ Frigate supports multiple different detectors that work on different types of ha
|
||||
- [Supports many model architectures](../../configuration/object_detectors#memryx-mx3)
|
||||
- Runs best with tiny, small, or medium-size models
|
||||
|
||||
- <CommunityBadge /> [DEEPX](#deepx-npu): The DEEPX NPU is available in m.2 format and as a HAT+ for the Raspberry Pi 5, allowing for a wide range of compatibility with devices.
|
||||
- [Supports YOLO model architectures](../../configuration/object_detectors#deepx-npu)
|
||||
- Runs best with tiny or small size models
|
||||
- Runs efficiently on low power hardware
|
||||
|
||||
**AMD**
|
||||
|
||||
- [ROCm](#rocm---amd-gpu): ROCm can run on AMD Discrete GPUs to provide efficient object detection
|
||||
@@ -262,32 +257,6 @@ The MX3 is a pipelined architecture, where the maximum frames per second support
|
||||
|
||||
Inference speeds may vary depending on the host platform. The above data was measured on an **Intel 13700 CPU**. Platforms like Raspberry Pi, Orange Pi, and other ARM-based SBCs have different levels of processing capability, which may limit total FPS.
|
||||
|
||||
### DEEPX NPU
|
||||
|
||||
Frigate supports the DEEPX NPU in both of its form factors: the **DX-M1** M.2 module, which works on x86 (Intel/AMD) and ARM-based SBCs such as the Raspberry Pi 5, and the **DX-M1M** on the [Sixfab AI HAT+](https://docs.sixfab.com/docs/ai-hat-plus-raspberry-pi-5-quickstart) for the Raspberry Pi 5. Both use the same driver and runtime, so the configuration is identical for either one. DEEPX NPU support in Frigate is developed and maintained by [Sixfab](https://sixfab.com).
|
||||
|
||||
The DEEPX driver and runtime run on the Docker host rather than inside the Frigate container and must be installed before the NPU can be used. See the [installation docs](installation.md#deepx-npu) for the setup steps and [the detector docs](/configuration/object_detectors#deepx-npu) for the configuration.
|
||||
|
||||
Frigate does not bundle a model for this detector. Models use DEEPX's `.dxnn` format, and pre-compiled YOLO models can be downloaded from the [DEEPX ModelZoo](https://developer.deepx.ai/modelzoo). Prefer a model with a `_ppu` suffix whenever one is available for the architecture you want: these run part of the post-processing on the NPU itself and are considerably faster, roughly 2.5x for the same architecture and input size. **YOLOX-S with PPU is the recommended starting point.**
|
||||
|
||||
Inference times for a few recommended models, measured through Frigate's own stats on a DX-M1:
|
||||
|
||||
| Model | Input Size | DX-M1 Inference Time |
|
||||
| ----------------- | ---------- | -------------------- |
|
||||
| YOLOX-S (PPU) | 640 | ~ 13 ms |
|
||||
| YOLOv9-t (PPU) | 640 | ~ 18 ms |
|
||||
| YOLOv4 (PPU) | 512 | ~ 20 ms |
|
||||
| YOLOX-S | 640 | ~ 34 ms |
|
||||
| YOLOv9-s | 640 | ~ 39 ms |
|
||||
|
||||
Other ModelZoo YOLO variants are also supported but have not been measured. Inference speeds vary with the host platform, so a slower host such as a Raspberry Pi 5 will report higher times than those above.
|
||||
|
||||
:::note
|
||||
|
||||
A few ModelZoo models can not be used with Frigate: SSD models (they are trained on Pascal VOC, so their labels do not match Frigate's), DAMO-YOLO models, face and pose models, and the PPU builds of YOLOv7.
|
||||
|
||||
:::
|
||||
|
||||
### Nvidia Jetson
|
||||
|
||||
Jetson devices are supported via the TensorRT or ONNX detectors when running Jetpack 6. It will [make use of the Jetson's hardware media engine](/configuration/hardware_acceleration_video#nvidia-jetson) when configured with the [appropriate presets](/configuration/ffmpeg_presets#hwaccel-presets), and will make use of the Jetson's GPU and DLA for object detection when configured with the [TensorRT detector](/configuration/object_detectors#nvidia-tensorrt-detector).
|
||||
|
||||
@@ -381,99 +381,6 @@ If you can't use Docker Compose, you can run the container with something simila
|
||||
|
||||
Finally, configure [hardware object detection](/configuration/object_detectors#memryx-mx3) to complete the setup.
|
||||
|
||||
### DEEPX NPU
|
||||
|
||||
The DEEPX NPU is available in two form factors, and Frigate supports both:
|
||||
|
||||
- **DX-M1** in the M.2 2280 form factor (like an NVMe SSD), for x86 (Intel/AMD) PCs, the Raspberry Pi 5, and other ARM SBCs with an exposed PCIe M.2 slot.
|
||||
- **DX-M1M** on the [Sixfab AI HAT+](https://docs.sixfab.com/docs/ai-hat-plus-raspberry-pi-5-quickstart), a HAT+ board that connects to the Raspberry Pi 5 over PCIe Gen 3 x1.
|
||||
|
||||
Both present the NPU through the same PCIe driver and DX-RT runtime, so the setup below and the detector configuration are identical for either one. Nothing needs to change when moving between them.
|
||||
|
||||
DEEPX NPU support in Frigate is developed and maintained by [Sixfab](https://sixfab.com).
|
||||
|
||||
#### Versions
|
||||
|
||||
A DEEPX install has several separately versioned pieces, and they all have to agree. The driver, the runtime, and the daemon live on the Docker host; Frigate itself carries only the Python bindings, which it downloads on first start:
|
||||
|
||||
| Component | Version | Installed on | Installed by |
|
||||
| -------------- | -------- | ------------ | ------------------------- |
|
||||
| Kernel driver | `v2.6.0` | Host | `user_installation.sh` |
|
||||
| DX-RT runtime | `v3.4.0` | Host | `user_installation.sh` |
|
||||
| NPU firmware | `v2.7.4` | The module | Flashed from the host |
|
||||
| DX-RT bindings | `v3.4.0` | Frigate | Downloaded at first start |
|
||||
|
||||
:::warning
|
||||
|
||||
A version mismatch does not produce a startup error. It typically shows up as inference requests that are accepted but never return a result, so detections simply stop appearing while Frigate looks healthy. If that happens after a Frigate upgrade, check every version in the table before anything else.
|
||||
|
||||
:::
|
||||
|
||||
The installation script installs the DX-RT runtime on the host and enables `dxrt.service`, so the daemon starts at boot and any other program on the host can share the NPU with Frigate. Check the firmware version with `dxrt-cli --status` and update the module if it does not match the table above.
|
||||
|
||||
#### Installation
|
||||
|
||||
The DEEPX kernel driver must be installed on the host rather than in the container, because containers share the host kernel and cannot load kernel modules. Installing it creates the `/dev/dxrt*` device nodes that are passed through to Frigate. The same script installs the DX-RT runtime and enables `dxrt.service`, the daemon that owns the NPU and hands work to it on behalf of Frigate and anything else on the host.
|
||||
|
||||
1. Copy or download [this script](https://github.com/blakeblackshear/frigate/blob/dev/docker/deepx/user_installation.sh).
|
||||
2. Ensure it has execution permissions with `sudo chmod +x user_installation.sh`
|
||||
3. Run the script with `./user_installation.sh`
|
||||
4. **Restart your computer** to complete driver installation.
|
||||
|
||||
Confirm the NPU is visible before continuing:
|
||||
|
||||
```bash
|
||||
ls /dev/dxrt*
|
||||
```
|
||||
|
||||
Then confirm the daemon is running and listening in `/run/dxrt`:
|
||||
|
||||
```bash
|
||||
systemctl is-active dxrt.service
|
||||
ls /run/dxrt/
|
||||
```
|
||||
|
||||
#### Setup
|
||||
|
||||
To set up Frigate, follow the default installation instructions, for example: `ghcr.io/blakeblackshear/frigate:stable`
|
||||
|
||||
#### Docker configuration
|
||||
|
||||
Frigate needs the NPU device node and the directory holding the daemon's socket:
|
||||
|
||||
```yaml
|
||||
services:
|
||||
frigate:
|
||||
devices:
|
||||
- /dev/dxrt0:/dev/dxrt0
|
||||
volumes:
|
||||
- /run/dxrt:/run/dxrt
|
||||
```
|
||||
|
||||
If you can't use Docker Compose, add `--device /dev/dxrt0:/dev/dxrt0 -v /run/dxrt:/run/dxrt` to your `docker run` command.
|
||||
|
||||
Add one `--device` per NPU, contiguously from `/dev/dxrt0`, since the client stops enumerating at the first gap.
|
||||
|
||||
The installation script configures `dxrt.service` to place its socket in `/run/dxrt` through a systemd drop-in. Mounting the directory rather than the socket file means the container sees the new socket after `dxrt.service` is restarted, rather than holding on to a deleted one.
|
||||
|
||||
`dxrtd` listens on an abstract socket as well, but that one does not cross into a container, so Frigate names the filesystem socket through `DXRT_DYNAMIC_IPC_ENDPOINT` on your behalf. Set that variable on the container yourself only if the daemon listens somewhere else, which means you also set it for `dxrtd` through its own systemd drop-in. The script writes `/etc/systemd/system/dxrt.service.d/frigate.conf` for exactly that, and has `dxrt.service` link the socket to `/tmp/dxrt_dynamic_ipc.sock` when it starts, so the host's own `dxrt-cli` and `dxtop` keep finding it at the default path they fall back to.
|
||||
|
||||
:::note
|
||||
|
||||
The DX-RT client exits when `dxrt.service` stops, so restart the Frigate container after restarting `dxrt.service`.
|
||||
|
||||
:::
|
||||
|
||||
The device node is needed as well as the socket, because the client opens the NPU directly even though the daemon arbitrates access. Without it, inference fails with `Device not found`.
|
||||
|
||||
`/dev/shm` does not need sharing.
|
||||
|
||||
The DX-RT python bindings are not shipped in the Frigate image. Frigate downloads them on first start when a DEEPX detector is configured, and caches them under `/config`.
|
||||
|
||||
#### Configuration
|
||||
|
||||
Finally, configure [hardware object detection](/configuration/object_detectors#deepx-npu) to complete the setup.
|
||||
|
||||
### Rockchip platform
|
||||
|
||||
Make sure that you use a linux distribution that comes with the rockchip BSP kernel 5.10 or 6.1 and necessary drivers (especially rkvdec2 and rknpu). To check, enter the following commands:
|
||||
|
||||
@@ -99,10 +99,6 @@ def main() -> None:
|
||||
print("*** End Config Validation Errors ***")
|
||||
print("*************************************************************")
|
||||
|
||||
# force a non-zero exit code for config failures
|
||||
if args.validate_config:
|
||||
sys.exit(1)
|
||||
|
||||
# attempt to start Frigate in recovery mode
|
||||
try:
|
||||
config = FrigateConfig.load(install=True, safe_load=True)
|
||||
|
||||
+2
-12
@@ -483,7 +483,7 @@ class FrigateApp:
|
||||
|
||||
def start_audio_processor(self) -> None:
|
||||
self.audio_process = AudioProcessor(
|
||||
self.config, self.camera_metrics, self.embeddings_metrics, self.stop_event
|
||||
self.config, self.camera_metrics, self.stop_event
|
||||
)
|
||||
self.audio_process.start()
|
||||
self.processes["audio_detector"] = self.audio_process.pid or 0
|
||||
@@ -556,20 +556,10 @@ class FrigateApp:
|
||||
"output",
|
||||
lambda: OutputProcess(self.config, self.stop_event),
|
||||
),
|
||||
(
|
||||
"audio_process",
|
||||
"audio_detector",
|
||||
lambda: AudioProcessor(
|
||||
self.config,
|
||||
self.camera_metrics,
|
||||
self.embeddings_metrics,
|
||||
self.stop_event,
|
||||
),
|
||||
),
|
||||
]
|
||||
|
||||
for attr, key, factory in specs:
|
||||
if getattr(self, attr, None) is None:
|
||||
if not hasattr(self, attr):
|
||||
continue
|
||||
|
||||
def on_restart(
|
||||
|
||||
@@ -273,16 +273,6 @@ def detect_memryx() -> DetectionHardware | None:
|
||||
return _hardware("memryx", "memryx", "MemryX MX3", units)
|
||||
|
||||
|
||||
def detect_deepx() -> DetectionHardware | None:
|
||||
"""Find DEEPX NPUs by their device nodes."""
|
||||
units = _dev_units("dxrt*", "deepx:PCIe:{index}", "PCIe")
|
||||
|
||||
if not units:
|
||||
return None
|
||||
|
||||
return _hardware("deepx", "deepx", "DEEPX NPU", units)
|
||||
|
||||
|
||||
def detect_rockchip() -> DetectionHardware | None:
|
||||
"""Find a Rockchip NPU by reading the SoC from the device tree."""
|
||||
compatible = _read(f"{PROC_ROOT}/device-tree/compatible")
|
||||
@@ -329,7 +319,6 @@ PROBES = (
|
||||
detect_coral_usb,
|
||||
detect_hailo,
|
||||
detect_memryx,
|
||||
detect_deepx,
|
||||
detect_intel_npu,
|
||||
detect_intel_gpu,
|
||||
detect_nvidia_gpu,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+31
-46
@@ -11,7 +11,6 @@ from typing import Any
|
||||
|
||||
import numpy as np
|
||||
|
||||
from frigate.camera import CameraMetrics
|
||||
from frigate.comms.detections_updater import DetectionPublisher, DetectionTypeEnum
|
||||
from frigate.comms.inter_process import InterProcessRequestor
|
||||
from frigate.config import CameraConfig, CameraInput, FrigateConfig
|
||||
@@ -37,7 +36,6 @@ from frigate.data_processing.common.audio_transcription.model import (
|
||||
from frigate.data_processing.real_time.audio_transcription import (
|
||||
AudioTranscriptionRealTimeProcessor,
|
||||
)
|
||||
from frigate.data_processing.types import DataProcessorMetrics
|
||||
from frigate.ffmpeg_presets import parse_preset_input
|
||||
from frigate.log import LogPipe, suppress_stderr_during
|
||||
from frigate.util.builtin import get_ffmpeg_arg_list, load_labels
|
||||
@@ -88,7 +86,6 @@ class AudioProcessor(FrigateProcess):
|
||||
self,
|
||||
config: FrigateConfig,
|
||||
camera_metrics: DictProxy,
|
||||
embeddings_metrics: DataProcessorMetrics,
|
||||
stop_event: MpEvent,
|
||||
):
|
||||
super().__init__(
|
||||
@@ -96,38 +93,8 @@ class AudioProcessor(FrigateProcess):
|
||||
)
|
||||
|
||||
self.camera_metrics = camera_metrics
|
||||
self.embeddings_metrics = embeddings_metrics
|
||||
self.config = config
|
||||
|
||||
def spawn_if_needed(self, camera: CameraConfig) -> None:
|
||||
"""Start an audio maintainer for the camera once everything it needs
|
||||
has arrived. Returning early leaves the camera for the next poll."""
|
||||
name = camera.name
|
||||
if name is None or name in self.audio_threads:
|
||||
return
|
||||
if not camera.enabled or not camera.audio.enabled:
|
||||
return
|
||||
# ffmpeg update may not have arrived yet
|
||||
if not any("audio" in i.roles for i in camera.ffmpeg.inputs):
|
||||
return
|
||||
# the camera maintainer creates metrics on its own poll of the same
|
||||
# add update and may not have gotten there yet
|
||||
metrics = self.camera_metrics.get(name)
|
||||
if metrics is None:
|
||||
return
|
||||
thread = AudioEventMaintainer(
|
||||
camera,
|
||||
self.config,
|
||||
metrics,
|
||||
self.embeddings_metrics,
|
||||
self.transcription_model_runner,
|
||||
self.stop_event, # type: ignore[arg-type]
|
||||
self.genai_manager,
|
||||
)
|
||||
self.audio_threads[name] = thread
|
||||
thread.start()
|
||||
self.logger.info(f"Audio maintainer started for {name}")
|
||||
|
||||
def __stop_audio_thread(self, camera: str) -> None:
|
||||
thread = self.audio_threads.pop(camera, None)
|
||||
if thread is None:
|
||||
@@ -183,8 +150,29 @@ class AudioProcessor(FrigateProcess):
|
||||
],
|
||||
)
|
||||
|
||||
def spawn_if_needed(camera: CameraConfig) -> None:
|
||||
name = camera.name
|
||||
if name is None or name in self.audio_threads:
|
||||
return
|
||||
if not camera.enabled or not camera.audio.enabled:
|
||||
return
|
||||
# ffmpeg update may not have arrived yet; wait for next poll
|
||||
if not any("audio" in i.roles for i in camera.ffmpeg.inputs):
|
||||
return
|
||||
thread = AudioEventMaintainer(
|
||||
camera,
|
||||
self.config,
|
||||
self.camera_metrics,
|
||||
self.transcription_model_runner,
|
||||
self.stop_event, # type: ignore[arg-type]
|
||||
self.genai_manager,
|
||||
)
|
||||
self.audio_threads[name] = thread
|
||||
thread.start()
|
||||
self.logger.info(f"Audio maintainer started for {name}")
|
||||
|
||||
for camera in self.config.cameras.values():
|
||||
self.spawn_if_needed(camera)
|
||||
spawn_if_needed(camera)
|
||||
|
||||
self.logger.info(f"Audio processor started (pid: {self.pid})")
|
||||
|
||||
@@ -194,14 +182,15 @@ class AudioProcessor(FrigateProcess):
|
||||
updated_topics = config_subscriber.check_for_updates()
|
||||
|
||||
# stop maintainers for removed cameras so their ffmpeg process is
|
||||
# torn down
|
||||
# torn down and they stop touching camera_metrics (which the camera
|
||||
# maintainer has already popped for the removed camera)
|
||||
for removed_camera in updated_topics.get(
|
||||
CameraConfigUpdateEnum.remove.name, []
|
||||
):
|
||||
self.__stop_audio_thread(removed_camera)
|
||||
|
||||
for camera in self.config.cameras.values():
|
||||
self.spawn_if_needed(camera)
|
||||
spawn_if_needed(camera)
|
||||
|
||||
config_subscriber.stop()
|
||||
|
||||
@@ -223,8 +212,7 @@ class AudioEventMaintainer(threading.Thread):
|
||||
self,
|
||||
camera: CameraConfig,
|
||||
config: FrigateConfig,
|
||||
metrics: CameraMetrics,
|
||||
embeddings_metrics: DataProcessorMetrics,
|
||||
camera_metrics: DictProxy,
|
||||
audio_transcription_model_runner: AudioTranscriptionModelRunner | None,
|
||||
stop_event: threading.Event,
|
||||
genai_manager: Any = None,
|
||||
@@ -233,11 +221,7 @@ class AudioEventMaintainer(threading.Thread):
|
||||
|
||||
self.config = config
|
||||
self.camera_config = camera
|
||||
# hold the metrics object rather than indexing the manager dict per
|
||||
# chunk, which costs an IPC round trip and breaks once the camera
|
||||
# maintainer pops the entry on removal
|
||||
self.metrics = metrics
|
||||
self.embeddings_metrics = embeddings_metrics
|
||||
self.camera_metrics = camera_metrics
|
||||
self.stop_event = stop_event
|
||||
# per-camera stop signal so a single maintainer can be torn down at
|
||||
# runtime (e.g. on camera removal) without stopping the whole process
|
||||
@@ -281,7 +265,7 @@ class AudioEventMaintainer(threading.Thread):
|
||||
camera_config=self.camera_config,
|
||||
requestor=self.requestor,
|
||||
model_runner=self.audio_transcription_model_runner,
|
||||
metrics=self.embeddings_metrics,
|
||||
metrics=self.camera_metrics[self.camera_config.name],
|
||||
stop_event=self.stop_event,
|
||||
genai_manager=self.genai_manager,
|
||||
)
|
||||
@@ -307,8 +291,8 @@ class AudioEventMaintainer(threading.Thread):
|
||||
audio_as_float: np.ndarray = audio.astype(np.float32)
|
||||
rms, dBFS = self.calculate_audio_levels(audio_as_float)
|
||||
|
||||
self.metrics.audio_rms.value = rms
|
||||
self.metrics.audio_dBFS.value = dBFS
|
||||
self.camera_metrics[self.camera_config.name].audio_rms.value = rms
|
||||
self.camera_metrics[self.camera_config.name].audio_dBFS.value = dBFS
|
||||
|
||||
audio_detections: list[tuple[str, float]] = []
|
||||
|
||||
@@ -393,6 +377,7 @@ class AudioEventMaintainer(threading.Thread):
|
||||
return
|
||||
|
||||
time.sleep(self.camera_config.ffmpeg.retry_interval)
|
||||
self.logpipe.dump()
|
||||
self.start_or_restart_ffmpeg()
|
||||
|
||||
if self.audio_listener is None or self.audio_listener.stdout is None:
|
||||
|
||||
@@ -144,14 +144,6 @@ class LogPipe(threading.Thread):
|
||||
self.pipeReader.close()
|
||||
|
||||
def dump(self) -> None:
|
||||
if not self.deque:
|
||||
return
|
||||
|
||||
self.logger.log(
|
||||
self.level,
|
||||
"The following ffmpeg logs include the last 100 lines prior to exit.",
|
||||
)
|
||||
|
||||
while len(self.deque) > 0:
|
||||
self.logger.log(self.level, self.deque.popleft())
|
||||
|
||||
|
||||
@@ -188,12 +188,8 @@ class ImprovedMotionDetector(MotionDetector):
|
||||
self.config.skip_motion_threshold is not None
|
||||
and pct_motion > self.config.skip_motion_threshold
|
||||
):
|
||||
# recalibrate so we transition to the new background. the frame
|
||||
# still has to be blended in here, otherwise the background stays
|
||||
# frozen and every subsequent frame skips as well
|
||||
# force a recalibration so we transition to the new background
|
||||
self.calibrating = True
|
||||
cv2.accumulateWeighted(resized_frame, self.avg_frame, 0.2)
|
||||
self.motion_frame_count = 0
|
||||
return []
|
||||
|
||||
# once the motion is less than 5% and the number of contours is < 4, assume its calibrated
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
"""Tests for audio maintainer spawning on runtime camera adds."""
|
||||
|
||||
import threading
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from frigate.config import FrigateConfig
|
||||
from frigate.events.audio import AudioProcessor
|
||||
|
||||
|
||||
def _build_config() -> FrigateConfig:
|
||||
return FrigateConfig(
|
||||
**{
|
||||
"mqtt": {"host": "mqtt"},
|
||||
"cameras": {
|
||||
"front_door": {
|
||||
"ffmpeg": {
|
||||
"inputs": [
|
||||
{
|
||||
"path": "rtsp://10.0.0.1:554/video",
|
||||
"roles": ["detect", "audio"],
|
||||
}
|
||||
]
|
||||
},
|
||||
"audio": {"enabled": True},
|
||||
}
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
class TestAudioSpawnIfNeeded(unittest.TestCase):
|
||||
def _processor(self, config: FrigateConfig, camera_metrics: dict) -> AudioProcessor:
|
||||
processor = AudioProcessor.__new__(AudioProcessor)
|
||||
processor.config = config
|
||||
processor.camera_metrics = camera_metrics
|
||||
processor.embeddings_metrics = MagicMock()
|
||||
processor.audio_threads = {}
|
||||
processor.transcription_model_runner = None
|
||||
processor.genai_manager = None
|
||||
processor.stop_event = threading.Event()
|
||||
processor.logger = MagicMock()
|
||||
return processor
|
||||
|
||||
def test_skips_camera_whose_metrics_have_not_been_created_yet(self):
|
||||
"""The camera maintainer creates metrics on its own poll of the add
|
||||
update, so the audio processor can see the camera first."""
|
||||
config = _build_config()
|
||||
processor = self._processor(config, {})
|
||||
|
||||
with patch("frigate.events.audio.AudioEventMaintainer") as maintainer:
|
||||
processor.spawn_if_needed(config.cameras["front_door"])
|
||||
|
||||
maintainer.assert_not_called()
|
||||
assert processor.audio_threads == {}
|
||||
|
||||
def test_spawns_once_metrics_exist_and_passes_the_metrics_object(self):
|
||||
config = _build_config()
|
||||
metrics = object()
|
||||
processor = self._processor(config, {"front_door": metrics})
|
||||
|
||||
with patch("frigate.events.audio.AudioEventMaintainer") as maintainer:
|
||||
processor.spawn_if_needed(config.cameras["front_door"])
|
||||
|
||||
assert maintainer.call_args.args[2] is metrics
|
||||
assert "front_door" in processor.audio_threads
|
||||
maintainer.return_value.start.assert_called_once()
|
||||
|
||||
def test_does_not_respawn_for_a_camera_already_running(self):
|
||||
config = _build_config()
|
||||
processor = self._processor(config, {"front_door": object()})
|
||||
processor.audio_threads["front_door"] = MagicMock()
|
||||
|
||||
with patch("frigate.events.audio.AudioEventMaintainer") as maintainer:
|
||||
processor.spawn_if_needed(config.cameras["front_door"])
|
||||
|
||||
maintainer.assert_not_called()
|
||||
|
||||
def test_skips_camera_whose_ffmpeg_update_has_not_arrived_yet(self):
|
||||
"""The add update carries the camera before its ffmpeg inputs are
|
||||
applied, so the audio role can be briefly missing."""
|
||||
config = _build_config()
|
||||
camera = config.cameras["front_door"]
|
||||
camera.ffmpeg.inputs[0].roles = ["detect"]
|
||||
processor = self._processor(config, {"front_door": object()})
|
||||
|
||||
with patch("frigate.events.audio.AudioEventMaintainer") as maintainer:
|
||||
processor.spawn_if_needed(camera)
|
||||
|
||||
maintainer.assert_not_called()
|
||||
@@ -1,896 +0,0 @@
|
||||
"""Tests for the DEEPX detector."""
|
||||
|
||||
import json
|
||||
import os
|
||||
import struct
|
||||
import sys
|
||||
import tempfile
|
||||
import unittest
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import numpy as np
|
||||
from pydantic import ValidationError
|
||||
|
||||
from frigate.detectors.detector_config import ModelConfig, ModelTypeEnum
|
||||
from frigate.detectors.device import (
|
||||
DeviceParseError,
|
||||
build_detector_config,
|
||||
parse_device,
|
||||
)
|
||||
from frigate.detectors.plugins.deepx import (
|
||||
DEEPX_MANIFEST,
|
||||
DXRT_VERSION,
|
||||
PPU_RECORD_SIZE,
|
||||
DeepxDetector,
|
||||
DeepxDetectorConfig,
|
||||
PpuLayout,
|
||||
YoloLayout,
|
||||
class_count,
|
||||
decode_raw_anchor,
|
||||
decode_raw_nms_in_head,
|
||||
infer_yolo_layout,
|
||||
read_ppu_layout,
|
||||
resolve_device,
|
||||
validate_yolox_outputs,
|
||||
)
|
||||
|
||||
|
||||
def model_with_type(model_type) -> ModelConfig:
|
||||
return ModelConfig(
|
||||
model_type=model_type,
|
||||
labelmap_path=None,
|
||||
labelmap={79: "toothbrush"},
|
||||
width=640,
|
||||
height=640,
|
||||
)
|
||||
|
||||
|
||||
def build_ppu_record(box, score=0.9, label=0, grid=(7, 9, 2, 2)) -> np.ndarray:
|
||||
record = np.zeros(PPU_RECORD_SIZE, dtype=np.uint8)
|
||||
record[0:16] = np.array(box, dtype=np.float32).view(np.uint8)
|
||||
record[16:20] = grid
|
||||
record[20:24] = np.array([score], dtype=np.float32).view(np.uint8)
|
||||
record[24:28] = np.array([label], dtype=np.uint32).view(np.uint8)
|
||||
return record.reshape(1, 1, PPU_RECORD_SIZE)
|
||||
|
||||
|
||||
# compile_config.ppu as DX-COM writes it for the two head kinds
|
||||
ANCHOR_BASED_PPU = {"type": 0, "num_classes": 80, "activation": "Sigmoid"}
|
||||
ANCHOR_FREE_PPU = {"type": 1, "num_classes": 80}
|
||||
|
||||
PPU_BBOX_NODE = "/head/Mul_2"
|
||||
|
||||
# (grid_w, grid_h, entries) per scale, finest first; the grids give the
|
||||
# strides at a 640 input
|
||||
THREE_SCALE_ANCHORS = [(80, 80, 3), (40, 40, 3), (20, 20, 3)]
|
||||
TWO_SCALE_ANCHORS = [(40, 40, 3), (20, 20, 3)]
|
||||
FOUR_SCALE_ANCHORS = [(160, 160, 3), (80, 80, 3), (40, 40, 3), (20, 20, 3)]
|
||||
THREE_SCALE_FREE = [(80, 80, 1), (40, 40, 1), (20, 20, 1)]
|
||||
ONE_SCALE_FREE = [(100, 84, 1)]
|
||||
|
||||
|
||||
def proto_varint(value: int) -> bytes:
|
||||
out = bytearray()
|
||||
while True:
|
||||
byte = value & 0x7F
|
||||
value >>= 7
|
||||
out.append(byte | (0x80 if value else 0))
|
||||
if not value:
|
||||
return bytes(out)
|
||||
|
||||
|
||||
def proto_bytes(field: int, payload: bytes) -> bytes:
|
||||
return proto_varint(field << 3 | 2) + proto_varint(len(payload)) + payload
|
||||
|
||||
|
||||
def proto_number(field: int, value: int) -> bytes:
|
||||
return proto_varint(field << 3) + proto_varint(value)
|
||||
|
||||
|
||||
def onnx_node(op_type: str, name: str, inputs: list, outputs: list) -> bytes:
|
||||
body = b"".join(proto_bytes(1, tensor.encode()) for tensor in inputs)
|
||||
body += b"".join(proto_bytes(2, tensor.encode()) for tensor in outputs)
|
||||
return body + proto_bytes(3, name.encode()) + proto_bytes(4, op_type.encode())
|
||||
|
||||
|
||||
def onnx_box_graph(box_format: str) -> bytes:
|
||||
if box_format == "broken":
|
||||
return proto_varint(1 << 3 | 3)
|
||||
|
||||
unnamed = box_format == "unnamed"
|
||||
|
||||
def graph_node(op_type: str, name: str, inputs: list, outputs: list) -> bytes:
|
||||
return onnx_node(op_type, "" if unnamed else name, inputs, outputs)
|
||||
|
||||
nodes = [
|
||||
graph_node("Split", "dfl_split", ["dfl", "sizes"], ["lt", "rb"]),
|
||||
graph_node("Sub", "corner_min", ["anchors", "lt"], ["x1y1"]),
|
||||
graph_node("Add", "corner_max", ["rb", "anchors"], ["x2y2"]),
|
||||
]
|
||||
if box_format in ("centre", "unnamed"):
|
||||
nodes += [
|
||||
graph_node("Add", "corner_sum", ["x1y1", "x2y2"], ["sum"]),
|
||||
graph_node("Mul", "corner_mean", ["sum", "half"], ["cxy"]),
|
||||
graph_node("Sub", "corner_span", ["x2y2", "x1y1"], ["wh"]),
|
||||
graph_node("Concat", "box_concat", ["cxy", "wh"], ["box"]),
|
||||
]
|
||||
elif box_format == "corner":
|
||||
nodes.append(graph_node("Concat", "box_concat", ["x1y1", "x2y2"], ["box"]))
|
||||
else:
|
||||
nodes.append(graph_node("Concat", "box_concat", ["x1y1", "x1y1"], ["box"]))
|
||||
|
||||
box = "box"
|
||||
if unnamed:
|
||||
box = "box_flat"
|
||||
nodes.append(graph_node("Reshape", "box_reshape", ["shape", "box"], [box]))
|
||||
|
||||
nodes.append(onnx_node("Mul", PPU_BBOX_NODE, [box, "strides"], ["bbox_out"]))
|
||||
graph = b"".join(proto_bytes(1, node) for node in nodes)
|
||||
graph += proto_bytes(5, b"weights")
|
||||
return (
|
||||
proto_number(1, 10) # ir_version
|
||||
+ proto_bytes(2, b"onnx_frontend_compiler") # producer_name
|
||||
+ proto_bytes(7, graph)
|
||||
)
|
||||
|
||||
|
||||
def write_dxnn(
|
||||
directory, ppu, layers, name="model.dxnn", table=True, box_format=None
|
||||
) -> str:
|
||||
"""A minimal .dxnn as DX-RT's parsers read it: the container header, a
|
||||
compile_config carrying `ppu`, and either the PPU tensor table with one
|
||||
entry per (layer, anchor) as a v8 file has, or with `table` False only
|
||||
the rmap_info listing of the PPU output tensors, as a v7 file has.
|
||||
`layers` is (grid_w, grid_h, entries) per scale, finest first; an
|
||||
anchor-free scale has one entry, and grid_h 1 means a flattened
|
||||
(1, cells, channels) tensor. `box_format`, "centre" or "corner", adds
|
||||
the compiled graph that says how the head writes its boxes, along with
|
||||
the compile_config layer naming the node the PPU reads them from."""
|
||||
if box_format is not None and "layer" not in ppu:
|
||||
ppu = dict(ppu, layer=[{"bbox": PPU_BBOX_NODE, "cls_conf": "/head/Sigmoid"}])
|
||||
|
||||
compile_config = json.dumps({"compile_version": "2.4.0", "ppu": ppu}).encode()
|
||||
graph = onnx_box_graph(box_format) if box_format is not None else b""
|
||||
|
||||
if table:
|
||||
part = bytearray(struct.pack("<BBBB", 1, sum(n for _, _, n in layers), 0, 0))
|
||||
for conv, (grid_w, grid_h, entries) in enumerate(layers):
|
||||
for anchor in range(entries):
|
||||
part += struct.pack(
|
||||
"<HHfBBBBBBBB",
|
||||
128,
|
||||
80,
|
||||
0.001,
|
||||
conv,
|
||||
anchor,
|
||||
0,
|
||||
1,
|
||||
0,
|
||||
grid_w,
|
||||
grid_h,
|
||||
0,
|
||||
)
|
||||
else:
|
||||
outputs = []
|
||||
for conv, (grid_w, grid_h, entries) in enumerate(layers):
|
||||
for anchor in range(entries):
|
||||
name_ = f"PPU_Transpose_Output_{conv}"
|
||||
if entries > 1:
|
||||
name_ += f"_anchor_{anchor}"
|
||||
shape = [1, grid_w, 127] if grid_h == 1 else [1, grid_h, grid_w, 128]
|
||||
outputs.append({"name": name_, "shape": shape, "layout": "PPU_YOLO"})
|
||||
part = json.dumps({"inputs": [], "outputs": outputs}).encode()
|
||||
|
||||
data = {
|
||||
"compile_config": {
|
||||
"type": "str",
|
||||
"offset": 0,
|
||||
"size": len(compile_config),
|
||||
},
|
||||
"compiled_data": {
|
||||
"M1A_4K": {
|
||||
"npu_0": {
|
||||
"rmap": {"type": "bytes", "offset": 0, "size": 0},
|
||||
"ppu" if table else "rmap_info": {
|
||||
"type": "bytes" if table else "str",
|
||||
"offset": len(compile_config),
|
||||
"size": len(part),
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
if graph:
|
||||
data["vis_npu_models"] = {
|
||||
"npu_0": {
|
||||
"type": "bytes",
|
||||
"offset": len(compile_config) + len(part),
|
||||
"size": len(graph),
|
||||
}
|
||||
}
|
||||
|
||||
index = json.dumps(
|
||||
{
|
||||
"version": 8 if table else 7,
|
||||
"signature": "DXNN",
|
||||
"size": 8192,
|
||||
"data": data,
|
||||
}
|
||||
).encode()
|
||||
|
||||
path = os.path.join(directory, name)
|
||||
with open(path, "wb") as model:
|
||||
model.write(b"DXNN" + struct.pack("<I", 8))
|
||||
model.write(index.ljust(8192 - 8, b"\0"))
|
||||
model.write(compile_config + part + graph)
|
||||
|
||||
return path
|
||||
|
||||
|
||||
def layout_of(shapes, num_classes, ppu=False, dynamic_output=False) -> YoloLayout:
|
||||
return infer_yolo_layout(shapes, num_classes, ppu, dynamic_output).layout
|
||||
|
||||
|
||||
class TestDeepxModelFile(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.tmp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(self.tmp.cleanup)
|
||||
|
||||
def layout(self, ppu, layers, **kwargs) -> PpuLayout | None:
|
||||
return read_ppu_layout(write_dxnn(self.tmp.name, ppu, layers, **kwargs))
|
||||
|
||||
def test_the_head_kind_and_one_grid_per_scale_are_read(self):
|
||||
cases = {
|
||||
"anchor-based: three anchors per scale collapse to one grid each": (
|
||||
(ANCHOR_BASED_PPU, THREE_SCALE_ANCHORS, {}),
|
||||
PpuLayout(anchor_based=True, grids=((80, 80), (40, 40), (20, 20))),
|
||||
),
|
||||
"anchor-free, one scale flattened into a single tensor": (
|
||||
(ANCHOR_FREE_PPU, ONE_SCALE_FREE, {"box_format": "centre"}),
|
||||
PpuLayout(anchor_based=False, grids=((100, 84),), centre_boxes=True),
|
||||
),
|
||||
"a head kind the compiler does not name still yields the scales": (
|
||||
({"type": 7}, [(80, 80, 3), (40, 40, 3)], {}),
|
||||
PpuLayout(anchor_based=None, grids=((80, 80), (40, 40))),
|
||||
),
|
||||
"no table: the per-anchor split says anchor-based": (
|
||||
({"num_classes": 80}, THREE_SCALE_ANCHORS, {"table": False}),
|
||||
PpuLayout(anchor_based=True, grids=((80, 80), (40, 40), (20, 20))),
|
||||
),
|
||||
"no table: compile_config places the scales ahead of the names": (
|
||||
(
|
||||
{
|
||||
"type": 1,
|
||||
"outputs": {
|
||||
f"PPU_Transpose_Output_{i}": {"conv_idx": 2 - i}
|
||||
for i in range(3)
|
||||
},
|
||||
},
|
||||
[(20, 20, 1), (40, 40, 1), (80, 80, 1)],
|
||||
{"table": False},
|
||||
),
|
||||
PpuLayout(anchor_based=False, grids=((80, 80), (40, 40), (20, 20))),
|
||||
),
|
||||
"no table: every scale in one (1, cells, channels) tensor": (
|
||||
(ANCHOR_FREE_PPU, [(8400, 1, 1)], {"table": False}),
|
||||
PpuLayout(anchor_based=False, grids=((8400, 1),)),
|
||||
),
|
||||
}
|
||||
|
||||
for head, ((ppu, layers, kwargs), expected) in cases.items():
|
||||
with self.subTest(head=head):
|
||||
self.assertEqual(self.layout(ppu, layers, **kwargs), expected)
|
||||
|
||||
def test_the_box_format_comes_from_the_compiled_graph(self):
|
||||
for box_format, centre in (
|
||||
("centre", True),
|
||||
("corner", False),
|
||||
("unnamed", True),
|
||||
):
|
||||
with self.subTest(box_format=box_format):
|
||||
self.assertEqual(
|
||||
self.layout(ANCHOR_FREE_PPU, ONE_SCALE_FREE, box_format=box_format),
|
||||
PpuLayout(
|
||||
anchor_based=False, grids=((100, 84),), centre_boxes=centre
|
||||
),
|
||||
)
|
||||
|
||||
def test_a_box_format_the_graph_does_not_answer_is_left_open(self):
|
||||
cases = {
|
||||
"no compiled graph at all": (ANCHOR_FREE_PPU, ONE_SCALE_FREE, {}),
|
||||
"a graph without the node compile_config names": (
|
||||
dict(ANCHOR_FREE_PPU, layer=[{"bbox": "/head/Missing"}]),
|
||||
ONE_SCALE_FREE,
|
||||
{"box_format": "centre"},
|
||||
),
|
||||
"a graph that builds its boxes from neither shape": (
|
||||
ANCHOR_FREE_PPU,
|
||||
ONE_SCALE_FREE,
|
||||
{"box_format": "neither"},
|
||||
),
|
||||
"a graph section the reader cannot make sense of": (
|
||||
ANCHOR_FREE_PPU,
|
||||
ONE_SCALE_FREE,
|
||||
{"box_format": "broken"},
|
||||
),
|
||||
"a grid-decoded head, where the question does not arise": (
|
||||
ANCHOR_FREE_PPU,
|
||||
THREE_SCALE_FREE,
|
||||
{"box_format": "centre"},
|
||||
),
|
||||
}
|
||||
|
||||
for graph, (ppu, layers, kwargs) in cases.items():
|
||||
with self.subTest(graph=graph):
|
||||
self.assertIsNone(self.layout(ppu, layers, **kwargs).centre_boxes)
|
||||
|
||||
def test_nothing_is_read_from_a_model_without_ppu_metadata(self):
|
||||
self.assertIsNone(read_ppu_layout(os.path.join(self.tmp.name, "missing")))
|
||||
|
||||
path = write_dxnn(self.tmp.name, None, [(80, 80, 3)])
|
||||
self.assertIsNone(read_ppu_layout(path))
|
||||
|
||||
with open(path, "wb") as model:
|
||||
model.write(b"ONNX" + b"\0" * 100)
|
||||
self.assertIsNone(read_ppu_layout(path))
|
||||
|
||||
path = write_dxnn(self.tmp.name, ANCHOR_BASED_PPU, [(80, 80, 3), (40, 40, 3)])
|
||||
os.truncate(path, os.path.getsize(path) - 40)
|
||||
self.assertIsNone(read_ppu_layout(path))
|
||||
|
||||
|
||||
class TestDeepxLayoutInference(unittest.TestCase):
|
||||
def test_a_shape_and_class_count_pick_one_layout(self):
|
||||
cases = {
|
||||
"anchor-free, four columns ahead of the classes": (
|
||||
[(1, 84, 8400)],
|
||||
80,
|
||||
YoloLayout.anchor_free,
|
||||
84,
|
||||
),
|
||||
"anchor-free, row-major": ([(1, 8400, 84)], 80, YoloLayout.anchor_free, 84),
|
||||
"anchor-based, an objectness column as well": (
|
||||
[(1, 25200, 85)],
|
||||
80,
|
||||
YoloLayout.anchor,
|
||||
85,
|
||||
),
|
||||
"anchor-based, channel-major": (
|
||||
[(1, 85, 25200)],
|
||||
80,
|
||||
YoloLayout.anchor,
|
||||
85,
|
||||
),
|
||||
"NMS in the head, a fixed run of corner records": (
|
||||
[(1, 300, 6)],
|
||||
80,
|
||||
YoloLayout.nms_in_head,
|
||||
None,
|
||||
),
|
||||
# only the label map can tell these two apart
|
||||
"85 columns with 81 classes is anchor-free": (
|
||||
[(1, 8400, 85)],
|
||||
81,
|
||||
YoloLayout.anchor_free,
|
||||
85,
|
||||
),
|
||||
"85 columns with 80 classes is anchor-based": (
|
||||
[(1, 8400, 85)],
|
||||
80,
|
||||
YoloLayout.anchor,
|
||||
85,
|
||||
),
|
||||
# 6 columns is all three layouts, told apart by the row count
|
||||
"6 columns and thousands of rows, one class": (
|
||||
[(1, 25200, 6)],
|
||||
1,
|
||||
YoloLayout.anchor,
|
||||
6,
|
||||
),
|
||||
"6 columns and thousands of rows, two classes": (
|
||||
[(1, 8400, 6)],
|
||||
2,
|
||||
YoloLayout.anchor_free,
|
||||
6,
|
||||
),
|
||||
"6 columns and a few hundred rows, one class": (
|
||||
[(1, 300, 6)],
|
||||
1,
|
||||
YoloLayout.nms_in_head,
|
||||
None,
|
||||
),
|
||||
"7 columns with two classes is only anchor-based": (
|
||||
[(1, 8400, 7)],
|
||||
2,
|
||||
YoloLayout.anchor,
|
||||
7,
|
||||
),
|
||||
# a square output matches the same width on both axes, which must
|
||||
# not read as two candidate layouts
|
||||
"a square output is not ambiguous with itself": (
|
||||
[(1, 85, 85)],
|
||||
80,
|
||||
YoloLayout.anchor,
|
||||
85,
|
||||
),
|
||||
"three NCHW maps with 255 channels are feature maps": (
|
||||
[(1, 255, 80, 80), (1, 255, 40, 40), (1, 255, 20, 20)],
|
||||
80,
|
||||
YoloLayout.multipart,
|
||||
None,
|
||||
),
|
||||
}
|
||||
|
||||
for head, (shapes, num_classes, layout, columns) in cases.items():
|
||||
with self.subTest(head=head):
|
||||
output = infer_yolo_layout(shapes, num_classes, False, False)
|
||||
|
||||
self.assertIs(output.layout, layout)
|
||||
if columns is not None:
|
||||
self.assertEqual(output.columns, columns)
|
||||
|
||||
def test_the_runtime_flags_outrank_the_shapes(self):
|
||||
self.assertIs(layout_of([(8400,)], 80, ppu=True), YoloLayout.ppu)
|
||||
self.assertIs(
|
||||
layout_of([(1, -1, 6)], 80, dynamic_output=True), YoloLayout.nms_in_head
|
||||
)
|
||||
|
||||
def test_a_shape_no_layout_fits_is_refused_with_the_reason(self):
|
||||
cases = {
|
||||
"fits two layouts": ([(1, 84, 6)], 80),
|
||||
"labelmap_path": ([(1, 8400, 84)], 91),
|
||||
"no output tensor": ([], 80),
|
||||
"255 channels": (
|
||||
[(1, 80, 80, 255), (1, 40, 40, 255), (1, 20, 20, 255)],
|
||||
80,
|
||||
),
|
||||
"feature maps": ([(1, 8400, 80), (1, 8400, 4)], 80),
|
||||
"80-class": ([(1, 24, 80, 80), (1, 24, 40, 40), (1, 24, 20, 20)], 3),
|
||||
}
|
||||
|
||||
for reason, (shapes, num_classes) in cases.items():
|
||||
with (
|
||||
self.subTest(reason=reason),
|
||||
self.assertRaisesRegex(ValueError, reason),
|
||||
):
|
||||
layout_of(shapes, num_classes)
|
||||
|
||||
|
||||
class TestDeepxOutputValidation(unittest.TestCase):
|
||||
def test_the_raw_yolox_head_is_read_for_the_configured_input(self):
|
||||
for shapes, size in (
|
||||
([(1, 8400, 85)], 640),
|
||||
([(1, 85, 8400)], 640),
|
||||
# 52*52 + 26*26 + 13*13 cells at 416
|
||||
([(1, 3549, 85)], 416),
|
||||
):
|
||||
with self.subTest(shapes=shapes, size=size):
|
||||
self.assertEqual(validate_yolox_outputs(shapes, 80, size, size), 85)
|
||||
|
||||
def test_another_head_under_yolox_is_refused_with_the_reason(self):
|
||||
cases = {
|
||||
"width and height": ([(1, 8400, 85)], 80, 416),
|
||||
"labelmap_path": ([(1, 8400, 85)], 91, 640),
|
||||
"yolo-generic": ([(1, 8400, 80), (1, 8400, 4)], 80, 640),
|
||||
}
|
||||
|
||||
for reason, (shapes, num_classes, size) in cases.items():
|
||||
with (
|
||||
self.subTest(reason=reason),
|
||||
self.assertRaisesRegex(ValueError, reason),
|
||||
):
|
||||
validate_yolox_outputs(shapes, num_classes, size, size)
|
||||
|
||||
def test_the_label_map_bounds_the_class_count(self):
|
||||
self.assertEqual(class_count({0: "person", 79: "toothbrush"}), 80)
|
||||
|
||||
with self.assertRaisesRegex(ValueError, "labelmap_path"):
|
||||
class_count({})
|
||||
|
||||
|
||||
class TestDeepxRawDecode(unittest.TestCase):
|
||||
def anchor_rows(self, rows) -> list:
|
||||
out = np.zeros((1, len(rows), 85), dtype=np.float32)
|
||||
|
||||
for i, (cx, cy, w, h, obj, label, score) in enumerate(rows):
|
||||
out[0, i, 0:4] = [cx, cy, w, h]
|
||||
out[0, i, 4] = obj
|
||||
out[0, i, 5 + label] = score
|
||||
|
||||
return [out]
|
||||
|
||||
def test_an_anchor_based_head_becomes_normalized_corners(self):
|
||||
outputs = self.anchor_rows([(320.0, 160.0, 64.0, 32.0, 0.8, 3, 0.5)])
|
||||
|
||||
detections = decode_raw_anchor(outputs, 640, 640, 0.25, 0.45)
|
||||
|
||||
self.assertEqual(detections[0][0], 3)
|
||||
self.assertAlmostEqual(detections[0][1], 0.4, places=5)
|
||||
self.assertAlmostEqual(detections[0][2], 144 / 640, places=5)
|
||||
self.assertAlmostEqual(detections[0][3], 288 / 640, places=5)
|
||||
self.assertAlmostEqual(detections[0][4], 176 / 640, places=5)
|
||||
self.assertAlmostEqual(detections[0][5], 352 / 640, places=5)
|
||||
|
||||
def test_a_channel_major_export_is_read_by_column_count(self):
|
||||
outputs = self.anchor_rows([(320.0, 160.0, 64.0, 32.0, 1.0, 3, 0.9)])
|
||||
|
||||
detections = decode_raw_anchor(
|
||||
[np.swapaxes(outputs[0], 1, 2)], 640, 640, 0.25, 0.45, columns=85
|
||||
)
|
||||
|
||||
self.assertEqual(detections[0][0], 3)
|
||||
self.assertAlmostEqual(detections[0][3], 288 / 640, places=5)
|
||||
|
||||
def test_rows_below_the_combined_threshold_are_dropped(self):
|
||||
# 0.4 * 0.5 = 0.2, under the threshold both parts clear on their own
|
||||
outputs = self.anchor_rows([(320.0, 320.0, 40.0, 80.0, 0.4, 3, 0.5)])
|
||||
|
||||
self.assertTrue(np.all(decode_raw_anchor(outputs, 640, 640, 0.25, 0.45) == 0))
|
||||
|
||||
def test_at_most_twenty_detections_are_returned(self):
|
||||
rows = [(20.0 + 24 * i, 320.0, 16.0, 16.0, 1.0, i % 80, 0.9) for i in range(25)]
|
||||
|
||||
detections = decode_raw_anchor(self.anchor_rows(rows), 640, 640, 0.25, 0.45)
|
||||
|
||||
self.assertEqual(detections.shape, (20, 6))
|
||||
self.assertEqual(int((detections[:, 1] > 0).sum()), 20)
|
||||
|
||||
def test_an_nms_in_head_output_is_read_without_running_nms(self):
|
||||
out = np.array(
|
||||
[
|
||||
[
|
||||
[100.0, 100.0, 200.0, 200.0, 0.9, 2.0],
|
||||
[102.0, 102.0, 202.0, 202.0, 0.8, 2.0],
|
||||
[300.0, 300.0, 400.0, 400.0, 0.1, 5.0],
|
||||
]
|
||||
],
|
||||
dtype=np.float32,
|
||||
)
|
||||
|
||||
detections = decode_raw_nms_in_head([out], 640, 640, 0.25)
|
||||
|
||||
self.assertEqual(detections[0][0], 2)
|
||||
self.assertAlmostEqual(detections[0][1], 0.9, places=5)
|
||||
self.assertAlmostEqual(detections[0][3], 100 / 640, places=5)
|
||||
self.assertEqual(detections[1][0], 2)
|
||||
self.assertAlmostEqual(detections[1][1], 0.8, places=5)
|
||||
self.assertTrue(np.all(detections[2] == 0))
|
||||
|
||||
empty = np.zeros((1, 0, 6), dtype=np.float32)
|
||||
self.assertTrue(np.all(decode_raw_nms_in_head([empty], 640, 640, 0.25) == 0))
|
||||
|
||||
|
||||
class TestDeepxConfig(unittest.TestCase):
|
||||
def test_a_device_string_resolves_to_an_npu_index(self):
|
||||
for configured, index in (("PCIe:1", 1), ("2", 2), ("", 0)):
|
||||
with self.subTest(device=configured):
|
||||
self.assertEqual(resolve_device(configured), index)
|
||||
|
||||
def test_a_device_that_is_not_an_index_is_rejected(self):
|
||||
"""The whole string has to be an index. Reading only the tail would
|
||||
take the 1 out of "PCIe:0,PCIe:1" and bind to an NPU the config never
|
||||
named, and several NPUs are configured as separate devices entries."""
|
||||
for configured in (
|
||||
"PCIe:the-fast-one",
|
||||
"PCIe:0,PCIe:1",
|
||||
"0,1",
|
||||
"PCIe:0 PCIe:1",
|
||||
"PCIe:-1",
|
||||
"PCIe:",
|
||||
):
|
||||
with self.subTest(device=configured):
|
||||
with self.assertRaises(ValueError):
|
||||
resolve_device(configured)
|
||||
|
||||
with self.assertRaises(ValidationError):
|
||||
DeepxDetectorConfig(type="deepx", device=configured)
|
||||
|
||||
def test_a_bad_device_is_refused_where_the_config_is_parsed(self):
|
||||
"""parse_device builds the detector config to surface a bad device at
|
||||
startup, so the comma-separated form fails there rather than binding a
|
||||
detector process to the wrong NPU."""
|
||||
self.assertEqual(parse_device("deepx:PCIe:1").device, "PCIe:1")
|
||||
|
||||
for raw in ("deepx:PCIe:0,PCIe:1", "deepx:the-fast-one"):
|
||||
with self.subTest(raw=raw), self.assertRaises(DeviceParseError):
|
||||
parse_device(raw)
|
||||
|
||||
def test_a_device_string_builds_this_detector_config(self):
|
||||
"""Frigate turns a `deepx:PCIe:0` entry into the detector config with
|
||||
the model already attached, which is the path app.py takes; a bare
|
||||
constructor call does not exercise it."""
|
||||
config = build_detector_config(
|
||||
parse_device("deepx:PCIe:0"), model_with_type(ModelTypeEnum.yologeneric)
|
||||
)
|
||||
|
||||
self.assertIsInstance(config, DeepxDetectorConfig)
|
||||
self.assertEqual(config.device, "PCIe:0")
|
||||
self.assertEqual(config.model.model_type, ModelTypeEnum.yologeneric)
|
||||
|
||||
def test_the_runtime_manifest_pins_its_wheels_to_the_version(self):
|
||||
"""A PyPI path carries a per-file digest, so bumping DXRT_VERSION has
|
||||
to rewrite the whole URL; a stale one installs the old wheel and fails
|
||||
the sha256 on every user's first start."""
|
||||
self.assertEqual(DEEPX_MANIFEST.version, DXRT_VERSION)
|
||||
|
||||
for artifact in DEEPX_MANIFEST.artifacts:
|
||||
with self.subTest(url=artifact.url):
|
||||
self.assertIn(f"dx_engine-{DXRT_VERSION}-", artifact.url)
|
||||
|
||||
def test_a_model_less_config_still_validates(self):
|
||||
config = DeepxDetectorConfig(type="deepx")
|
||||
|
||||
self.assertIsNone(config.model)
|
||||
|
||||
|
||||
class DeepxDetectorTestCase(unittest.TestCase):
|
||||
def detector(
|
||||
self,
|
||||
model_type=ModelTypeEnum.yologeneric,
|
||||
outputs_info=None,
|
||||
ppu=False,
|
||||
dynamic=False,
|
||||
model_path="/nonexistent/model.dxnn",
|
||||
) -> DeepxDetector:
|
||||
dx_engine = MagicMock()
|
||||
dx_engine.Configuration.ITEM.SERVICE = object()
|
||||
session = dx_engine.InferenceEngine.return_value
|
||||
session.get_output_tensors_info.return_value = (
|
||||
[{"shape": [8400]}] if ppu else outputs_info or []
|
||||
)
|
||||
session.is_ppu.return_value = ppu
|
||||
session.has_dynamic_output.return_value = dynamic
|
||||
|
||||
config = DeepxDetectorConfig(type="deepx")
|
||||
config.model = model_with_type(model_type)
|
||||
config.model.path = model_path
|
||||
|
||||
with (
|
||||
# the detector writes the endpoint into the environment, which the
|
||||
# rest of the suite shares when it runs in one process
|
||||
patch.dict(os.environ),
|
||||
patch.dict(sys.modules, {"dx_engine": dx_engine}),
|
||||
patch.object(DeepxDetector, "activate_dependencies"),
|
||||
patch("os.path.isfile", return_value=True),
|
||||
):
|
||||
return DeepxDetector(config)
|
||||
|
||||
def ppu_detector(
|
||||
self, ppu, layers, model_type=ModelTypeEnum.yologeneric, box_format=None
|
||||
) -> DeepxDetector:
|
||||
tmp = tempfile.TemporaryDirectory()
|
||||
self.addCleanup(tmp.cleanup)
|
||||
|
||||
return self.detector(
|
||||
model_type,
|
||||
ppu=True,
|
||||
model_path=write_dxnn(tmp.name, ppu, layers, box_format=box_format),
|
||||
)
|
||||
|
||||
def detect(self, detector, outputs) -> np.ndarray:
|
||||
detector.session.run.return_value = outputs
|
||||
return detector.detect_raw(np.zeros((1, 640, 640, 3), np.uint8))
|
||||
|
||||
|
||||
class TestDeepxModelType(DeepxDetectorTestCase):
|
||||
def test_a_model_type_with_no_decoder_is_rejected(self):
|
||||
for model_type in (ModelTypeEnum.ssd, ModelTypeEnum.dfine):
|
||||
with (
|
||||
self.subTest(model_type=model_type),
|
||||
self.assertRaisesRegex(ValueError, model_type.value),
|
||||
):
|
||||
self.detector(model_type)
|
||||
|
||||
def test_supported_model_types_are_accepted(self):
|
||||
for model_type, outputs_info in (
|
||||
(ModelTypeEnum.yologeneric, [{"shape": [1, 84, 8400]}]),
|
||||
(ModelTypeEnum.yolox, [{"shape": [1, 8400, 85]}]),
|
||||
):
|
||||
with self.subTest(model_type=model_type):
|
||||
detector = self.detector(model_type, outputs_info)
|
||||
|
||||
self.assertEqual(detector.model_type, model_type)
|
||||
|
||||
|
||||
class TestDeepxDetectorLoad(DeepxDetectorTestCase):
|
||||
def test_the_layout_is_settled_at_load(self):
|
||||
detector = self.detector(ModelTypeEnum.yologeneric, [{"shape": [1, 84, 8400]}])
|
||||
self.assertIs(detector.output.layout, YoloLayout.anchor_free)
|
||||
self.assertEqual(detector.output.columns, 84)
|
||||
|
||||
detector = self.detector(ModelTypeEnum.yolox, [{"shape": [1, 8400, 85]}])
|
||||
self.assertIs(detector.output.layout, YoloLayout.yolox)
|
||||
|
||||
for model_type in (ModelTypeEnum.yologeneric, ModelTypeEnum.yolox):
|
||||
with self.subTest(model_type=model_type):
|
||||
detector = self.ppu_detector(
|
||||
ANCHOR_FREE_PPU, THREE_SCALE_FREE, model_type=model_type
|
||||
)
|
||||
|
||||
self.assertIs(detector.output.layout, YoloLayout.ppu)
|
||||
self.assertEqual(detector.ppu_layout.scale_count, 3)
|
||||
|
||||
def test_a_model_the_detector_cannot_decode_is_refused_at_load(self):
|
||||
cases = {
|
||||
"Cannot decode DEEPX model": lambda: self.detector(
|
||||
ModelTypeEnum.yologeneric, [{"shape": [1, 8400, 7]}]
|
||||
),
|
||||
"DX-COM 2.4.0": lambda: self.detector(ModelTypeEnum.yologeneric, ppu=True),
|
||||
"face and pose": lambda: self.ppu_detector({"type": 2}, [(80, 80, 1)]),
|
||||
"centre and size or as two corners": lambda: self.ppu_detector(
|
||||
ANCHOR_FREE_PPU, ONE_SCALE_FREE
|
||||
),
|
||||
}
|
||||
|
||||
for reason, load in cases.items():
|
||||
with (
|
||||
self.subTest(reason=reason),
|
||||
self.assertRaisesRegex(ValueError, reason),
|
||||
):
|
||||
load()
|
||||
|
||||
|
||||
class TestDeepxDetectRaw(DeepxDetectorTestCase):
|
||||
def test_a_ppu_record_decodes_by_the_head_in_the_model(self):
|
||||
cases = {
|
||||
"anchor-based, layer 2 of 3 at stride 32, the 373x326 anchor": (
|
||||
(ANCHOR_BASED_PPU, THREE_SCALE_ANCHORS, None),
|
||||
build_ppu_record((0.6, 0.4, 0.3, 0.7), label=5),
|
||||
(5, (0.0, 0.380094, 0.864187, 0.589906)),
|
||||
),
|
||||
"anchor-based, layer 0 of 3 at stride 8, the 16x30 anchor": (
|
||||
(ANCHOR_BASED_PPU, THREE_SCALE_ANCHORS, None),
|
||||
build_ppu_record((0.6, 0.4, 0.3, 0.7), grid=(7, 9, 1, 0)),
|
||||
(0, (None, 0.116750, None, None)),
|
||||
),
|
||||
"anchor-based, two scales: layer 0 is stride 16, not stride 8": (
|
||||
(ANCHOR_BASED_PPU, TWO_SCALE_ANCHORS, None),
|
||||
build_ppu_record((0.6, 0.4, 0.3, 0.7), grid=(7, 9, 1, 0)),
|
||||
(0, (0.141156, 0.236031, 0.223844, 0.248969)),
|
||||
),
|
||||
"anchor-free, three scales: cell (10, 9) of stride 32": (
|
||||
(ANCHOR_FREE_PPU, THREE_SCALE_FREE, None),
|
||||
build_ppu_record((1.2, 0.5, 1.0, 0.5), grid=(9, 10, 0, 2), label=7),
|
||||
(7, (0.433782, 0.492043, 0.516218, 0.627957)),
|
||||
),
|
||||
"anchor-free, one scale: the box fields are already pixels": (
|
||||
(ANCHOR_FREE_PPU, ONE_SCALE_FREE, "centre"),
|
||||
build_ppu_record((320.0, 160.0, 64.0, 32.0), label=3),
|
||||
(3, (144 / 640, 288 / 640, 176 / 640, 352 / 640)),
|
||||
),
|
||||
"anchor-free, one scale: a sub-pixel box stays sub-pixel": (
|
||||
(ANCHOR_FREE_PPU, ONE_SCALE_FREE, "centre"),
|
||||
build_ppu_record((0.6, 0.4, 0.3, 0.7)),
|
||||
(0, (None, 0.45 / 640, None, None)),
|
||||
),
|
||||
"a corner-format head reads the record as two corners": (
|
||||
(ANCHOR_FREE_PPU, ONE_SCALE_FREE, "corner"),
|
||||
build_ppu_record((100.0, 50.0, 300.0, 250.0), label=2),
|
||||
(2, (50 / 640, 100 / 640, 250 / 640, 300 / 640)),
|
||||
),
|
||||
"a centre-format head reads it as a centre and size": (
|
||||
(ANCHOR_FREE_PPU, ONE_SCALE_FREE, "centre"),
|
||||
build_ppu_record((100.0, 50.0, 300.0, 250.0), label=2),
|
||||
(2, (0.0, 0.0, 175 / 640, 250 / 640)),
|
||||
),
|
||||
}
|
||||
|
||||
for head, ((ppu, layers, box_format), record, (label, box)) in cases.items():
|
||||
with self.subTest(head=head):
|
||||
detector = self.ppu_detector(ppu, layers, box_format=box_format)
|
||||
|
||||
detections = self.detect(detector, [record])
|
||||
|
||||
self.assertEqual(detections[0][0], label)
|
||||
for i, expected in enumerate(box, start=2):
|
||||
if expected is not None:
|
||||
self.assertAlmostEqual(detections[0][i], expected, places=5)
|
||||
|
||||
def test_the_strides_come_from_the_grids_in_the_model(self):
|
||||
detector = self.ppu_detector(
|
||||
ANCHOR_FREE_PPU, [(40, 40, 1), (20, 20, 1), (10, 10, 1)]
|
||||
)
|
||||
|
||||
detections = self.detect(
|
||||
detector,
|
||||
[build_ppu_record((1.2, 0.5, 1.0, 0.5), grid=(9, 10, 0, 0), label=7)],
|
||||
)
|
||||
|
||||
# layer 0 is stride 16: centre (11.2, 9.5) * 16, size e * 16 x sqrt(e) * 16
|
||||
self.assertEqual(detections[0][0], 7)
|
||||
self.assertAlmostEqual(detections[0][2], (152 - np.exp(0.5) * 8) / 640, 5)
|
||||
self.assertAlmostEqual(detections[0][3], (179.2 - np.exp(1.0) * 8) / 640, 5)
|
||||
|
||||
def test_the_head_stays_what_the_model_said_across_frames(self):
|
||||
detector = self.ppu_detector(ANCHOR_BASED_PPU, THREE_SCALE_ANCHORS)
|
||||
|
||||
first = self.detect(
|
||||
detector, [build_ppu_record((0.6, 0.4, 0.3, 0.7), grid=(7, 9, 1, 0))]
|
||||
)
|
||||
# layer 0 of 3: stride 8, anchor 16x30
|
||||
self.assertAlmostEqual(first[0][3], 0.116750, places=5)
|
||||
|
||||
second = self.detect(
|
||||
detector, [build_ppu_record((0.5, 0.5, 0.4, 0.4), grid=(3, 4, 0, 1))]
|
||||
)
|
||||
# layer 1 of 3: stride 16, anchor 30x61, not layer 1 of 2
|
||||
self.assertAlmostEqual(second[0][3], 0.0975, places=5)
|
||||
|
||||
detector = self.ppu_detector(
|
||||
ANCHOR_FREE_PPU, ONE_SCALE_FREE, box_format="centre"
|
||||
)
|
||||
record = [build_ppu_record((100.0, 50.0, 300.0, 250.0), label=2)]
|
||||
# centre (100, 50), size 300 x 250: the right edge lands at 250
|
||||
for frame in range(2):
|
||||
with self.subTest(frame=frame):
|
||||
self.assertAlmostEqual(
|
||||
self.detect(detector, record)[0][5], 250 / 640, places=5
|
||||
)
|
||||
|
||||
def test_records_the_head_cannot_place_come_back_empty(self):
|
||||
cases = {
|
||||
"a level or box the anchor table does not carry": (
|
||||
THREE_SCALE_ANCHORS,
|
||||
[build_ppu_record((0.6, 0.4, 0.3, 0.7), grid=(7, 9, 2, 5))],
|
||||
),
|
||||
"a scale count Frigate has no anchor table for": (
|
||||
FOUR_SCALE_ANCHORS,
|
||||
[build_ppu_record((0.6, 0.4, 0.3, 0.7))],
|
||||
),
|
||||
"a record below the score threshold": (
|
||||
THREE_SCALE_ANCHORS,
|
||||
[build_ppu_record((0.6, 0.4, 0.3, 0.7), score=0.1)],
|
||||
),
|
||||
"an unexpected record width": (
|
||||
THREE_SCALE_ANCHORS,
|
||||
[np.zeros((1, 3, 16), dtype=np.uint8)],
|
||||
),
|
||||
**{
|
||||
f"no records at all, shaped {shape}": (
|
||||
THREE_SCALE_ANCHORS,
|
||||
[np.zeros(shape, dtype=np.uint8)],
|
||||
)
|
||||
for shape in ((1, 0, PPU_RECORD_SIZE), (0, PPU_RECORD_SIZE), (0,))
|
||||
},
|
||||
}
|
||||
|
||||
for output, (layers, outputs) in cases.items():
|
||||
with self.subTest(output=output):
|
||||
detector = self.ppu_detector(ANCHOR_BASED_PPU, layers)
|
||||
|
||||
self.assertTrue(np.all(self.detect(detector, outputs) == 0))
|
||||
|
||||
def test_a_yolox_raw_head_is_decoded_through_the_grid(self):
|
||||
detector = self.detector(ModelTypeEnum.yolox, [{"shape": [1, 8400, 85]}])
|
||||
|
||||
# cell (x 10, y 5) of the stride-8 grid is row 5 * 80 + 10
|
||||
tensor = np.zeros((1, 8400, 85), np.float32)
|
||||
tensor[0, 410, :5] = [0.5, 0.5, np.log(4.0), np.log(2.0), 0.9]
|
||||
tensor[0, 410, 5 + 7] = 0.8
|
||||
|
||||
detections = self.detect(detector, [tensor])
|
||||
|
||||
# centre (84, 44), size 32 x 16
|
||||
self.assertEqual(detections[0][0], 7)
|
||||
self.assertAlmostEqual(detections[0][1], 0.72, places=5)
|
||||
self.assertAlmostEqual(detections[0][2], 36 / 640, places=5)
|
||||
self.assertAlmostEqual(detections[0][3], 68 / 640, places=5)
|
||||
self.assertAlmostEqual(detections[0][4], 52 / 640, places=5)
|
||||
self.assertAlmostEqual(detections[0][5], 100 / 640, places=5)
|
||||
|
||||
detector = self.detector(ModelTypeEnum.yolox, [{"shape": [1, 85, 8400]}])
|
||||
detections = self.detect(detector, [np.swapaxes(tensor, 1, 2)])
|
||||
self.assertAlmostEqual(detections[0][5], 100 / 640, places=5)
|
||||
|
||||
def test_a_raw_head_comes_back_as_frigates_detection_rows(self):
|
||||
detector = self.detector(ModelTypeEnum.yologeneric, [{"shape": [1, 84, 8400]}])
|
||||
output = np.zeros((1, 84, 8400), dtype=np.float32)
|
||||
output[0, 0:4, 0] = [320.0, 160.0, 64.0, 32.0]
|
||||
output[0, 4 + 2, 0] = 0.9
|
||||
|
||||
detections = self.detect(detector, [output])
|
||||
|
||||
self.assertEqual(detections.shape, (20, 6))
|
||||
self.assertEqual(detections[0][0], 2)
|
||||
self.assertAlmostEqual(detections[0][1], 0.9, places=5)
|
||||
self.assertAlmostEqual(detections[0][3], 288 / 640, places=5)
|
||||
@@ -184,26 +184,6 @@ class TestAccelerators(HardwareProbeTestCase):
|
||||
)
|
||||
self.assertFalse(memryx.unlimited)
|
||||
|
||||
def test_each_deepx_node_is_a_unit(self):
|
||||
write(os.path.join(self.dev_root, "dxrt0"))
|
||||
write(os.path.join(self.dev_root, "dxrt1"))
|
||||
|
||||
deepx = self.probe()["deepx"]
|
||||
|
||||
self.assertEqual(
|
||||
[unit.device for unit in deepx.units],
|
||||
["deepx:PCIe:0", "deepx:PCIe:1"],
|
||||
)
|
||||
|
||||
def test_a_deepx_npu_is_unlimited(self):
|
||||
# the host daemon multiplexes, so one module takes several processes
|
||||
write(os.path.join(self.dev_root, "dxrt0"))
|
||||
|
||||
self.assertTrue(self.probe()["deepx"].unlimited)
|
||||
|
||||
def test_no_deepx_is_reported_without_a_node(self):
|
||||
self.assertNotIn("deepx", self.probe())
|
||||
|
||||
def test_a_supported_rockchip_soc_is_reported(self):
|
||||
write(
|
||||
os.path.join(self.proc_root, "device-tree", "compatible"),
|
||||
|
||||
@@ -73,35 +73,6 @@ class TestImprovedMotionDetector(unittest.TestCase):
|
||||
"Motion boxes should be empty when scene change exceeds skip threshold",
|
||||
)
|
||||
|
||||
def _bright_frame(self, offset: int) -> np.ndarray:
|
||||
"""Produce a bright frame with a small dark object that moves."""
|
||||
frame = np.full((self.frame_shape[0], self.frame_shape[1]), 200, dtype=np.uint8)
|
||||
x = 10 + (offset * 5) % 60
|
||||
frame[40:60, x : x + 15] = 20
|
||||
return frame
|
||||
|
||||
def test_skip_motion_threshold_recovers_after_skip(self):
|
||||
"""Skipped frames must still be blended into the background.
|
||||
|
||||
A bright scene differs from the zeroed background across the whole
|
||||
frame, so the first frames are skipped. The background has to catch up
|
||||
anyway, otherwise motion detection never returns.
|
||||
"""
|
||||
self.config.skip_motion_threshold = 0.5
|
||||
self.config.improve_contrast = False
|
||||
self.detector.config = self.config
|
||||
self.detector.update_mask()
|
||||
|
||||
boxes = [len(self.detector.detect(self._bright_frame(i))) for i in range(40)]
|
||||
|
||||
self.assertEqual(boxes[0], 0, "First frame should exceed the skip threshold")
|
||||
self.assertGreater(
|
||||
self.detector.avg_frame.max(),
|
||||
0,
|
||||
"Background was never updated while frames were skipped",
|
||||
)
|
||||
self.assertTrue(any(boxes), "Motion detection never recovered after a skip")
|
||||
|
||||
def test_skip_motion_threshold_does_not_affect_calibration(self):
|
||||
"""Even when skipping, the detector should go into calibrating state."""
|
||||
self.config.skip_motion_threshold = 0.4
|
||||
|
||||
@@ -324,7 +324,9 @@ class NorfairTracker(ObjectTracker):
|
||||
):
|
||||
tracker = self.get_tracker(obj["label"])
|
||||
tracker.tracked_objects = [
|
||||
o for o in tracker.tracked_objects if str(o.global_id) != track_id
|
||||
o
|
||||
for o in tracker.tracked_objects
|
||||
if str(o.global_id) != track_id and o.hit_counter < 0
|
||||
]
|
||||
|
||||
del self.track_id_map[track_id]
|
||||
|
||||
@@ -49,9 +49,6 @@ def start_or_restart_ffmpeg(
|
||||
if ffmpeg_process is not None:
|
||||
stop_ffmpeg(ffmpeg_process, logger)
|
||||
|
||||
# flush after the stop so the logs cover ffmpeg's output up to exit
|
||||
logpipe.dump()
|
||||
|
||||
if frame_size is None:
|
||||
process = sp.Popen(
|
||||
ffmpeg_cmd,
|
||||
|
||||
@@ -319,6 +319,9 @@ class CameraWatchdog(threading.Thread):
|
||||
f"Capture thread for {self.config.name} did not exit in time"
|
||||
)
|
||||
|
||||
self.logger.error(
|
||||
"The following ffmpeg logs include the last 100 lines prior to exit."
|
||||
)
|
||||
self.logpipe.dump()
|
||||
self.logger.info("Restarting ffmpeg...")
|
||||
self.start_ffmpeg_detect()
|
||||
@@ -540,6 +543,7 @@ class CameraWatchdog(threading.Thread):
|
||||
f"{self.config.name}/status/{role.value}", "offline"
|
||||
)
|
||||
|
||||
p["logpipe"].dump()
|
||||
p["process"] = start_or_restart_ffmpeg(
|
||||
p["cmd"], self.logger, p["logpipe"], ffmpeg_process=p["process"]
|
||||
)
|
||||
|
||||
@@ -56,14 +56,3 @@ export async function waitForErrorMarker(
|
||||
.poll(() => hasErrorMarkers(page), { timeout: timeoutMs })
|
||||
.toBe(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Append a trailing comment so the editor content differs from the
|
||||
* loaded config. The save buttons are disabled until then.
|
||||
*/
|
||||
export async function makeMonacoEdit(page: Page): Promise<void> {
|
||||
const editor = page.locator(".monaco-editor").first();
|
||||
await editor.click();
|
||||
await page.keyboard.press("ControlOrMeta+End");
|
||||
await page.keyboard.type("# edited by e2e", { delay: 0 });
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import { installWsFrameCapture, waitForWsFrame } from "../helpers/ws-frames";
|
||||
import { grantClipboardPermissions, readClipboard } from "../helpers/clipboard";
|
||||
import {
|
||||
getMonacoVisibleText,
|
||||
makeMonacoEdit,
|
||||
replaceMonacoValue,
|
||||
waitForErrorMarker,
|
||||
} from "../helpers/monaco";
|
||||
@@ -72,7 +71,6 @@ test.describe("Config Editor — Save @medium", () => {
|
||||
await expect(frigateApp.page.locator(".monaco-editor").first()).toBeVisible(
|
||||
{ timeout: 15_000 },
|
||||
);
|
||||
await makeMonacoEdit(frigateApp.page);
|
||||
await frigateApp.page.getByLabel("Save Only").click();
|
||||
await expect
|
||||
.poll(() => capture.capturedUrl(), { timeout: 5_000 })
|
||||
@@ -94,7 +92,6 @@ test.describe("Config Editor — Save @medium", () => {
|
||||
await expect(frigateApp.page.locator(".monaco-editor").first()).toBeVisible(
|
||||
{ timeout: 15_000 },
|
||||
);
|
||||
await makeMonacoEdit(frigateApp.page);
|
||||
await frigateApp.page.getByLabel("Save Only").click();
|
||||
await expect(frigateApp.page.getByText(/Invalid field/i)).toBeVisible({
|
||||
timeout: 5_000,
|
||||
@@ -120,7 +117,6 @@ test.describe("Config Editor — Save and Restart @medium", () => {
|
||||
{ timeout: 15_000 },
|
||||
);
|
||||
|
||||
await makeMonacoEdit(frigateApp.page);
|
||||
await frigateApp.page.getByLabel("Save & Restart").click();
|
||||
const dialog = frigateApp.page.getByRole("alertdialog");
|
||||
await expect(dialog).toBeVisible({ timeout: 5_000 });
|
||||
@@ -144,7 +140,6 @@ test.describe("Config Editor — Save and Restart @medium", () => {
|
||||
{ timeout: 15_000 },
|
||||
);
|
||||
|
||||
await makeMonacoEdit(frigateApp.page);
|
||||
await frigateApp.page.getByLabel("Save & Restart").click();
|
||||
const dialog = frigateApp.page.getByRole("alertdialog");
|
||||
await expect(dialog).toBeVisible({ timeout: 5_000 });
|
||||
|
||||
@@ -124,65 +124,6 @@ test.describe("genai provider settings @medium", () => {
|
||||
await expect(frigateApp.page.getByText(UNSAVED)).toBeVisible();
|
||||
});
|
||||
|
||||
test("switching back to the saved provider drops the other provider's model", async ({
|
||||
frigateApp,
|
||||
}) => {
|
||||
await installRoutes(
|
||||
frigateApp.page,
|
||||
{
|
||||
provider: "openai",
|
||||
model: "gpt-4o",
|
||||
roles: ["descriptions"],
|
||||
},
|
||||
{ models: ["gpt-4o", "qwen3"], supports_transcription: true },
|
||||
);
|
||||
await frigateApp.goto(SETTINGS_URL);
|
||||
|
||||
const model = frigateApp.page.locator(`#root_${ENTRY}_model`);
|
||||
const provider = frigateApp.page.locator(`#root_${ENTRY}_provider`);
|
||||
await expect(model).toHaveText("gpt-4o");
|
||||
|
||||
await provider.click();
|
||||
await frigateApp.page.getByRole("option", { name: "llamacpp" }).click();
|
||||
await model.click();
|
||||
await frigateApp.page.getByRole("option", { name: "qwen3" }).click();
|
||||
await expect(model).toHaveText("qwen3");
|
||||
|
||||
// the model picked for llamacpp must not carry over to openai, and the
|
||||
// saved one isn't filled back in since the endpoint may have changed
|
||||
await provider.click();
|
||||
await frigateApp.page
|
||||
.getByRole("option", { name: "openai", exact: true })
|
||||
.click();
|
||||
|
||||
await expect(model).toHaveText(MODEL_PLACEHOLDER);
|
||||
});
|
||||
|
||||
test("undo after switching provider brings back the saved model", async ({
|
||||
frigateApp,
|
||||
}) => {
|
||||
await installRoutes(
|
||||
frigateApp.page,
|
||||
{
|
||||
provider: "openai",
|
||||
model: "gpt-4o",
|
||||
roles: ["descriptions"],
|
||||
},
|
||||
{ models: ["gpt-4o"], supports_transcription: true },
|
||||
);
|
||||
await frigateApp.goto(SETTINGS_URL);
|
||||
|
||||
const model = frigateApp.page.locator(`#root_${ENTRY}_model`);
|
||||
await frigateApp.page.locator(`#root_${ENTRY}_provider`).click();
|
||||
await frigateApp.page.getByRole("option", { name: "llamacpp" }).click();
|
||||
await expect(model).toHaveText(MODEL_PLACEHOLDER);
|
||||
|
||||
await frigateApp.page.getByRole("button", { name: "Undo" }).click();
|
||||
|
||||
await expect(model).toHaveText("gpt-4o");
|
||||
await expect(frigateApp.page.getByText(UNSAVED)).toBeHidden();
|
||||
});
|
||||
|
||||
test("picking a model that cannot transcribe strips the role", async ({
|
||||
frigateApp,
|
||||
}) => {
|
||||
|
||||
@@ -15,6 +15,10 @@
|
||||
"bandwidth": {
|
||||
"title": "العرض الترددي:",
|
||||
"short": "العرض الترددي"
|
||||
},
|
||||
"latency": {
|
||||
"title": "التأخير:",
|
||||
"value": "{{seconds}} ثانية"
|
||||
}
|
||||
},
|
||||
"streamOffline": {
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
"1hour": "1 гадзіна",
|
||||
"12hours": "12 гадзін",
|
||||
"24hours": "24 гадзіны",
|
||||
"pm": "pm",
|
||||
"am": "am",
|
||||
"pm": "вечара",
|
||||
"am": "раніцы",
|
||||
"yr": "{{time}} г",
|
||||
"year_one": "{{time}} год",
|
||||
"year_few": "{{time}} гады",
|
||||
@@ -168,16 +168,13 @@
|
||||
"saveAll": "Захаваць усё",
|
||||
"savingAll": "Захаванне ўсяго…",
|
||||
"undoAll": "Адрабіць усё",
|
||||
"retry": "Паўтарыць",
|
||||
"expand": "Разгарнуць",
|
||||
"collapse": "Згарнуць",
|
||||
"reload": "Перазагрузіць"
|
||||
"retry": "Паўтарыць"
|
||||
},
|
||||
"menu": {
|
||||
"system": "Сістэма",
|
||||
"systemMetrics": "Стан і метрыкі",
|
||||
"systemMetrics": "Сістэмныя метрыкі",
|
||||
"configuration": "Канфігурацыя",
|
||||
"systemLogs": "Журналы",
|
||||
"systemLogs": "Журналы сістэмы",
|
||||
"profiles": "Профілі",
|
||||
"settings": "Налады",
|
||||
"configurationEditor": "Рэдактар канфігурацыі",
|
||||
@@ -228,7 +225,7 @@
|
||||
"withSystem": {
|
||||
"label": "Выкарыстоўваць мову з налад сістэмы"
|
||||
},
|
||||
"be": "Беларуская (беларуская)"
|
||||
"be": "Беларуская"
|
||||
},
|
||||
"appearance": "Выгляд",
|
||||
"darkMode": {
|
||||
@@ -331,36 +328,5 @@
|
||||
"validation_errors": "Памылкі праверкі",
|
||||
"credentialField": {
|
||||
"savedPlaceholder": "Захавана - пакіньце пустым, каб не мяняць"
|
||||
},
|
||||
"error": {
|
||||
"title": "Гэтая старонка перастала працаваць",
|
||||
"desc": "На старонцы адбылася нечаканая памылка. Звычайна дапамагае перазагрузка. Калі гэта паўтараецца, скапіюйце падрабязнасці і дадайце іх да абмеркавання на GitHub.",
|
||||
"staleTitle": "Патрэбна перазагрузка",
|
||||
"staleDesc": "Частка інтэрфейсу не загрузілася - звычайна гэта значыць, што Frigate абнавіўся, пакуль гэтая ўкладка была адкрытая. Перазагрузіце, каб атрымаць новую версію.",
|
||||
"partial": "Частка інтэрфейсу перастала працаваць.",
|
||||
"copyDetails": "Скапіяваць падрабязнасці",
|
||||
"copyFailed": "Не ўдалося скапіяваць падрабязнасці ў буфер абмену"
|
||||
},
|
||||
"commandMenu": {
|
||||
"title": "Меню каманд",
|
||||
"description": "Пошук старонак, камер, налад і дзеянняў",
|
||||
"placeholder": "Пошук старонак, камер, налад і дзеянняў",
|
||||
"empty": "Няма супадзенняў",
|
||||
"hint": "{{key}} або / каб адкрыць, Enter каб выканаць",
|
||||
"section": {
|
||||
"recent": "Апошнія",
|
||||
"pages": "Старонкі",
|
||||
"cameras": "Камеры",
|
||||
"cameraGroups": "Групы камер",
|
||||
"settings": "Налады",
|
||||
"actions": "Дзеянні"
|
||||
},
|
||||
"camera": {
|
||||
"live": "Эфір",
|
||||
"review": "Разгляд"
|
||||
},
|
||||
"action": {
|
||||
"toggleTheme": "Пераключыць светлы і цёмны рэжым"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,15 +137,6 @@
|
||||
"queueingExport": "Экспарт ставіцца ў чаргу…",
|
||||
"previewExport": "Перадпрагляд экспарту",
|
||||
"useThisRange": "Ужыць гэты прамежак"
|
||||
},
|
||||
"stream": {
|
||||
"label": "Якасць",
|
||||
"auto": "Аўта",
|
||||
"main": "Зыходная",
|
||||
"sub": "Нізкая",
|
||||
"autoDesc": "Выкарыстоўвае асноўную плынь, а дзе яна недаступная - пераходзіць на дадатковую плынь ніжэйшай якасці.",
|
||||
"mainDesc": "Экспартуе толькі асноўную плынь зыходнай якасці. Прамежкі часу, дзе асноўная плынь недаступная, будуць адсутнічаць.",
|
||||
"subDesc": "Экспартуе толькі дадатковую плынь ніжэйшай якасці. Прамежкі часу, дзе дадатковая плынь недаступная, будуць адсутнічаць."
|
||||
}
|
||||
},
|
||||
"streaming": {
|
||||
@@ -199,14 +190,7 @@
|
||||
"export": "Экспарт",
|
||||
"markAsReviewed": "Пазначыць як разгледжанае",
|
||||
"markAsUnreviewed": "Пазначыць як неразгледжанае",
|
||||
"deleteNow": "Выдаліць зараз",
|
||||
"generateDescription": "Стварыць апісанне"
|
||||
},
|
||||
"genaiDescription": {
|
||||
"toast": {
|
||||
"success": "Апісанне GenAI запытана для гэтага элемента разгляду.",
|
||||
"error": "Не ўдалося запытаць апісанне: {{error}}"
|
||||
}
|
||||
"deleteNow": "Выдаліць зараз"
|
||||
}
|
||||
},
|
||||
"imagePicker": {
|
||||
|
||||
@@ -22,6 +22,14 @@
|
||||
"title": "Паласа прапускання:",
|
||||
"short": "Паласа"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Затрымка:",
|
||||
"value": "{{seconds}} сек",
|
||||
"short": {
|
||||
"title": "Затрымка",
|
||||
"value": "{{seconds}} с"
|
||||
}
|
||||
},
|
||||
"totalFrames": "Усяго кадраў:",
|
||||
"droppedFrames": {
|
||||
"title": "Страчаныя кадры:",
|
||||
@@ -38,22 +46,7 @@
|
||||
"submittedFrigatePlus": "Кадр паспяхова адпраўлены ў Frigate+"
|
||||
},
|
||||
"error": {
|
||||
"submitFrigatePlusFailed": "Не ўдалося адправіць кадр у Frigate+",
|
||||
"playRecordingsFailed": "Не ўдалося прайграць запісы (памылка {{code}}): {{message}}"
|
||||
"submitFrigatePlusFailed": "Не ўдалося адправіць кадр у Frigate+"
|
||||
}
|
||||
},
|
||||
"quality": {
|
||||
"auto": "Аўта",
|
||||
"autoLow": "Прайграецца нізкая якасць (абмежаваная паласа прапускання)",
|
||||
"autoLowCodec": "Прайграецца нізкая якасць (зыходная не падтрымліваецца гэтым браўзерам)",
|
||||
"autoLowSaveData": "Прайграецца нізкая якасць (эканомія трафіку)",
|
||||
"main": "Зыходная",
|
||||
"sub": "Нізкая",
|
||||
"notSupportedBrowser": "Не падтрымліваецца гэтым браўзерам",
|
||||
"label": "Якасць",
|
||||
"noAudio": "Без гуку",
|
||||
"audioRate": "Гук {{rate}} кГц",
|
||||
"audioCodecRate": "{{codec}} {{rate}} кГц",
|
||||
"noRecordings": "Няма запісаў у гэтым прамежку часу"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
},
|
||||
"objects": {
|
||||
"label": "Аб'екты-трыгеры",
|
||||
"description": "Спіс тыпаў аб'ектаў (з карты метак), якія могуць спрацаваць у гэтай зоне. Можа быць радком або спісам радкоў. Калі пуста, улічваюцца ўсе аб'екты."
|
||||
"description": "Спіс тыпаў аб'ектаў (з labelmap), якія могуць спрацаваць у гэтай зоне. Можа быць радком або спісам радкоў. Калі пуста, улічваюцца ўсе аб'екты."
|
||||
}
|
||||
},
|
||||
"label": "CameraConfig",
|
||||
@@ -120,10 +120,6 @@
|
||||
"num_threads": {
|
||||
"label": "Патокі дэтэктавання",
|
||||
"description": "Колькасць патокаў для апрацоўкі дэтэктавання гуку."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "Змяненне карты метак гуку",
|
||||
"description": "Перавызначэнні або пераназначэнні, якія аб'ядноўваюцца са стандартнай картай метак гуку."
|
||||
}
|
||||
},
|
||||
"audio_transcription": {
|
||||
@@ -151,10 +147,6 @@
|
||||
"order": {
|
||||
"label": "Пазіцыя",
|
||||
"description": "Лічбавае становішча, якое вызначае парадак камеры ў раскладцы Birdseye."
|
||||
},
|
||||
"modes": {
|
||||
"label": "Тыпы актыўнасці",
|
||||
"description": "Тыпы актыўнасці, пры якіх камеры паказваюцца ў Birdseye."
|
||||
}
|
||||
},
|
||||
"detect": {
|
||||
@@ -215,10 +207,6 @@
|
||||
"annotation_offset": {
|
||||
"label": "Зрух анатацый",
|
||||
"description": "На колькі мілісекунд зрушыць прамавугольнікі аб'ектаў, каб яны супадалі з запісаным відэа: плыні «detect» і «record» рэдка ідэальна сінхронныя. Можа быць дадатным або адмоўным."
|
||||
},
|
||||
"scene": {
|
||||
"label": "Сцэна дэтэктавання",
|
||||
"description": "Асяроддзе, на якое глядзіць гэтая камера; паводле яго выбіраецца, якая з наладжаных мадэлей на ёй працуе. Камеры са значэннем «all» выкарыстоўваюць мадэль, наладжаную са сцэнай «all»."
|
||||
}
|
||||
},
|
||||
"face_recognition": {
|
||||
@@ -262,10 +250,6 @@
|
||||
"record": {
|
||||
"label": "Выходныя аргументы для record",
|
||||
"description": "Прадвызначаныя выходныя аргументы для плыняў з роляй «record»."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "Выходныя аргументы запісу дадатковай плыні",
|
||||
"description": "Выходныя аргументы для плыняў з роляй «record_sub». Калі не зададзена, выкарыстоўваюцца выходныя аргументы запісу."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
@@ -595,54 +579,6 @@
|
||||
"enabled_in_config": {
|
||||
"label": "Зыходны стан запісу",
|
||||
"description": "Паказвае, ці быў запіс уключаны ў зыходнай статычнай канфігурацыі."
|
||||
},
|
||||
"sub": {
|
||||
"label": "Запіс дадатковай плыні",
|
||||
"description": "Налады запісу другой плыні ніжэйшай якасці.",
|
||||
"enabled": {
|
||||
"label": "Уключыць запіс дадатковай плыні",
|
||||
"description": "Уключыць запіс другой плыні ніжэйшай якасці для прайгравання з адаптыўнай якасцю і падоўжанага захоўвання."
|
||||
},
|
||||
"continuous": {
|
||||
"label": "Бесперапыннае захоўванне дадатковай плыні",
|
||||
"description": "Колькасць дзён захоўвання запісаў дадатковай плыні незалежна ад аб'ектаў пад адсочваннем або руху.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Дзён захоўвання запісаў."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "Захоўванне дадатковай плыні па руху",
|
||||
"description": "Колькасць дзён захоўвання запісаў дадатковай плыні, выкліканых рухам.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Дзён захоўвання запісаў."
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"label": "Захоўванне абвестак дадатковай плыні",
|
||||
"description": "Налады захоўвання запісаў абвестак дадатковай плыні.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Колькасць дзён захоўвання запісаў падзей дэтэктавання."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Рэжым захоўвання",
|
||||
"description": "Рэжым захоўвання: all (усе сегменты), motion (сегменты з рухам) або active_objects (сегменты з актыўнымі аб'ектамі)."
|
||||
}
|
||||
},
|
||||
"detections": {
|
||||
"label": "Захоўванне дэтэктаванняў дадатковай плыні",
|
||||
"description": "Налады захоўвання запісаў дэтэктаванняў дадатковай плыні.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Колькасць дзён захоўвання запісаў падзей дэтэктавання."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Рэжым захоўвання",
|
||||
"description": "Рэжым захоўвання: all (усе сегменты), motion (сегменты з рухам) або active_objects (сегменты з актыўнымі аб'ектамі)."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
@@ -734,10 +670,6 @@
|
||||
"activity_context_prompt": {
|
||||
"label": "Прампт кантэксту актыўнасці",
|
||||
"description": "Уласны прампт, які апісвае, якая актыўнасць падазроная, а якая не, каб даць кантэкст для зводак GenAI."
|
||||
},
|
||||
"response_style": {
|
||||
"label": "Стыль адказу",
|
||||
"description": "Гатовы стыль пісьма для створаных апісанняў разгляду. Гатовыя стылі наладжваюць тон і падрабязнасць загалоўка, зводкі і апісання сцэны, якія бачыць карыстальнік; «default» пакідае ўбудаваны прампт без змен."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -33,11 +33,7 @@
|
||||
"label": "Патокі дэтэктавання",
|
||||
"description": "Колькасць патокаў для апрацоўкі дэтэктавання гуку."
|
||||
},
|
||||
"description": "Налады дэтэктавання падзей па гуку для ўсіх камер. Можна перавызначыць для кожнай камеры.",
|
||||
"labelmap": {
|
||||
"label": "Змяненне карты метак гуку",
|
||||
"description": "Перавызначэнні або пераназначэнні, якія аб'ядноўваюцца са стандартнай картай метак гуку."
|
||||
}
|
||||
"description": "Налады дэтэктавання падзей па гуку для ўсіх камер. Можна перавызначыць для кожнай камеры."
|
||||
},
|
||||
"audio_transcription": {
|
||||
"label": "Транскрыпцыя гуку",
|
||||
@@ -109,10 +105,6 @@
|
||||
"idle_heartbeat_fps": {
|
||||
"label": "FPS сігналу пры прастоі",
|
||||
"description": "Колькі разоў на секунду паўтараць апошні кадр Birdseye пры прастоі. 0 адключае."
|
||||
},
|
||||
"modes": {
|
||||
"label": "Тыпы актыўнасці",
|
||||
"description": "Тыпы актыўнасці, пры якіх камеры паказваюцца ў Birdseye."
|
||||
}
|
||||
},
|
||||
"detect": {
|
||||
@@ -173,10 +165,6 @@
|
||||
"annotation_offset": {
|
||||
"label": "Зрух анатацый",
|
||||
"description": "На колькі мілісекунд зрушыць прамавугольнікі аб'ектаў, каб яны супадалі з запісаным відэа: плыні «detect» і «record» рэдка ідэальна сінхронныя. Можа быць дадатным або адмоўным."
|
||||
},
|
||||
"scene": {
|
||||
"label": "Сцэна дэтэктавання",
|
||||
"description": "Асяроддзе, на якое глядзіць гэтая камера; паводле яго выбіраецца, якая з наладжаных мадэлей на ёй працуе. Камеры са значэннем «all» выкарыстоўваюць мадэль, наладжаную са сцэнай «all»."
|
||||
}
|
||||
},
|
||||
"face_recognition": {
|
||||
@@ -250,10 +238,6 @@
|
||||
"record": {
|
||||
"label": "Выходныя аргументы для record",
|
||||
"description": "Прадвызначаныя выходныя аргументы для плыняў з роляй «record»."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "Выходныя аргументы запісу дадатковай плыні",
|
||||
"description": "Выходныя аргументы для плыняў з роляй «record_sub». Калі не зададзена, выкарыстоўваюцца выходныя аргументы запісу."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
@@ -666,55 +650,7 @@
|
||||
"label": "Зыходны стан запісу",
|
||||
"description": "Паказвае, ці быў запіс уключаны ў зыходнай статычнай канфігурацыі."
|
||||
},
|
||||
"description": "Налады запісу і захоўвання для камер, калі яны не перавызначаны асобна.",
|
||||
"sub": {
|
||||
"label": "Запіс дадатковай плыні",
|
||||
"description": "Налады запісу другой плыні ніжэйшай якасці.",
|
||||
"enabled": {
|
||||
"label": "Уключыць запіс дадатковай плыні",
|
||||
"description": "Уключыць запіс другой плыні ніжэйшай якасці для прайгравання з адаптыўнай якасцю і падоўжанага захоўвання."
|
||||
},
|
||||
"continuous": {
|
||||
"label": "Бесперапыннае захоўванне дадатковай плыні",
|
||||
"description": "Колькасць дзён захоўвання запісаў дадатковай плыні незалежна ад аб'ектаў пад адсочваннем або руху.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Дзён захоўвання запісаў."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "Захоўванне дадатковай плыні па руху",
|
||||
"description": "Колькасць дзён захоўвання запісаў дадатковай плыні, выкліканых рухам.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Дзён захоўвання запісаў."
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"label": "Захоўванне абвестак дадатковай плыні",
|
||||
"description": "Налады захоўвання запісаў абвестак дадатковай плыні.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Колькасць дзён захоўвання запісаў падзей дэтэктавання."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Рэжым захоўвання",
|
||||
"description": "Рэжым захоўвання: all (усе сегменты), motion (сегменты з рухам) або active_objects (сегменты з актыўнымі аб'ектамі)."
|
||||
}
|
||||
},
|
||||
"detections": {
|
||||
"label": "Захоўванне дэтэктаванняў дадатковай плыні",
|
||||
"description": "Налады захоўвання запісаў дэтэктаванняў дадатковай плыні.",
|
||||
"days": {
|
||||
"label": "Дні захоўвання",
|
||||
"description": "Колькасць дзён захоўвання запісаў падзей дэтэктавання."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Рэжым захоўвання",
|
||||
"description": "Рэжым захоўвання: all (усе сегменты), motion (сегменты з рухам) або active_objects (сегменты з актыўнымі аб'ектамі)."
|
||||
}
|
||||
}
|
||||
}
|
||||
"description": "Налады запісу і захоўвання для камер, калі яны не перавызначаны асобна."
|
||||
},
|
||||
"review": {
|
||||
"label": "Разгляд",
|
||||
@@ -804,10 +740,6 @@
|
||||
"activity_context_prompt": {
|
||||
"label": "Прампт кантэксту актыўнасці",
|
||||
"description": "Уласны прампт, які апісвае, якая актыўнасць падазроная, а якая не, каб даць кантэкст для зводак GenAI."
|
||||
},
|
||||
"response_style": {
|
||||
"label": "Стыль адказу",
|
||||
"description": "Гатовы стыль пісьма для створаных апісанняў разгляду. Гатовыя стылі наладжваюць тон і падрабязнасць загалоўка, зводкі і апісання сцэны, якія бачыць карыстальнік; «default» пакідае ўбудаваны прампт без змен."
|
||||
}
|
||||
},
|
||||
"description": "Налады, якія кіруюць абвесткамі, дэтэктаваннямі і зводкамі разгляду GenAI для інтэрфейсу і сховішча."
|
||||
@@ -1241,7 +1173,7 @@
|
||||
},
|
||||
"default_role": {
|
||||
"label": "Прадвызначаная роля",
|
||||
"description": "Роля, якая прызначаецца карыстальнікам, аўтарызаваным праз проксі, калі супастаўленне роляў не спрацавала. Задайце «none», каб адмовіць у доступе карыстальнікам без супастаўлення."
|
||||
"description": "Роля, якая прызначаецца карыстальнікам, аўтарызаваным праз проксі, калі супастаўленне роляў не спрацавала."
|
||||
},
|
||||
"separator": {
|
||||
"label": "Сімвал-раздзяляльнік",
|
||||
@@ -1467,57 +1399,5 @@
|
||||
"label": "Паказваць у разглядзе",
|
||||
"description": "Ці бачная гэта камера ў разглядзе (старонка разгляду і яе фільтр камер, разгляд руху і выгляд гісторыі)."
|
||||
}
|
||||
},
|
||||
"models": {
|
||||
"label": "Мадэлі дэтэктавання",
|
||||
"description": "Мадэлі дэтэктавання аб'ектаў і абсталяванне, на якім працуе кожная з іх. Камера выбірае мадэль, супастаўляючы свой detect.scene са сцэнай мадэлі.",
|
||||
"scene": {
|
||||
"label": "Сцэна мадэлі",
|
||||
"description": "Асяроддзе камеры, для якога прызначана гэтая мадэль. Камера выбірае мадэль, задаючы detect.scene з адпаведным значэннем, а «all» выкарыстоўвае любая камера, якая нічога не задала."
|
||||
},
|
||||
"devices": {
|
||||
"label": "Абсталяванне дэтэктавання",
|
||||
"description": "Абсталяванне, на якім працуе гэтая мадэль, у выглядзе «<detector>» або «<detector>:<device>» (напрыклад «edgetpu:pci:0» ці «openvino:GPU»). Калі адна прылада пазначана некалькі разоў, на ёй запускаюцца дадатковыя працэсы вывядзення."
|
||||
},
|
||||
"path": {
|
||||
"label": "Шлях да мадэлі свайго дэтэктара аб'ектаў",
|
||||
"description": "Шлях да файла свае мадэлі дэтэктавання (або plus://<model_id> для мадэлей Frigate+)."
|
||||
},
|
||||
"labelmap_path": {
|
||||
"label": "Карта метак для свайго дэтэктара аб'ектаў",
|
||||
"description": "Шлях да файла карты метак, які супастаўляе лікавыя класы з тэкставымі меткамі для дэтэктара."
|
||||
},
|
||||
"width": {
|
||||
"label": "Шырыня ўваходу мадэлі дэтэктавання аб'ектаў",
|
||||
"description": "Шырыня ўваходнага тэнзара мадэлі ў пікселях."
|
||||
},
|
||||
"height": {
|
||||
"label": "Вышыня ўваходу мадэлі дэтэктавання аб'ектаў",
|
||||
"description": "Вышыня ўваходнага тэнзара мадэлі ў пікселях."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "Змяненне карты метак",
|
||||
"description": "Перавызначэнні або пераназначэнні, якія аб'ядноўваюцца са стандартнай картай метак."
|
||||
},
|
||||
"attributes_map": {
|
||||
"label": "Карта метак аб'ектаў да іх метак атрыбутаў",
|
||||
"description": "Супастаўленне метак аб'ектаў з меткамі атрыбутаў, якія дадаюць метаданыя (напрыклад «car» -> ['license_plate'])."
|
||||
},
|
||||
"input_tensor": {
|
||||
"label": "Форма ўваходнага тэнзара мадэлі",
|
||||
"description": "Фармат тэнзара, якога чакае мадэль: «nhwc» або «nchw»."
|
||||
},
|
||||
"input_pixel_format": {
|
||||
"label": "Фармат колеру пікселяў на ўваходзе мадэлі",
|
||||
"description": "Каляровая прастора пікселяў, якой чакае мадэль: «rgb», «bgr» або «yuv»."
|
||||
},
|
||||
"input_dtype": {
|
||||
"label": "Тып даных на ўваходзе мадэлі",
|
||||
"description": "Тып даных уваходнага тэнзара мадэлі (напрыклад «float32»)."
|
||||
},
|
||||
"model_type": {
|
||||
"label": "Тып мадэлі дэтэктавання аб'ектаў",
|
||||
"description": "Тып архітэктуры мадэлі дэтэктара (ssd, yolox, yolonas, yolo-generic, rfdetr, dfine), які некаторыя дэтэктары выкарыстоўваюць для аптымізацыі."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,5 @@
|
||||
},
|
||||
"detect": {
|
||||
"dimensionMustBeEven": "Мусіць быць цотным лікам."
|
||||
},
|
||||
"models": {
|
||||
"defaultRequired": "Адна мадэль мусіць выкарыстоўваць сцэну «All cameras». Без гэтага камера, якая не выбрала сцэну, не мае мадэлі, да якой можна вярнуцца."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,6 @@
|
||||
"auto_scroll": {
|
||||
"title": "Аўтапракрутка",
|
||||
"desc": "Сачыць за новымі паведамленнямі па меры паступлення."
|
||||
},
|
||||
"always_allow": {
|
||||
"title": "Заўсёды дазволеныя дзеянні",
|
||||
"desc": "Дзеянні, якія памочнік можа выконваць без папярэдняга запыту.",
|
||||
"none": "Няма",
|
||||
"reset": "Скінуць"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
@@ -74,15 +68,5 @@
|
||||
},
|
||||
"thinking": {
|
||||
"toggle": "Пераключыць разважанне"
|
||||
},
|
||||
"approval": {
|
||||
"title": "Ухваліць {{tool}}?",
|
||||
"desc": "Гэтае дзеянне нешта змяняе ў Frigate. Праглядзіце падрабязнасці перад ухваленнем.",
|
||||
"approve": "Ухваліць",
|
||||
"always_allow": "Заўсёды дазваляць",
|
||||
"reject": "Адхіліць",
|
||||
"approved": "Ухвалена",
|
||||
"rejected": "Адхілена",
|
||||
"placeholder": "Ухваліце або адхіліце дзеянне ў чаканні, каб працягнуць"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,5 @@
|
||||
"crop": "Абрэзаць па фільтры",
|
||||
"cropAria": "Пераключыць абрэзку перадпрагляду па выбраных вобласцях",
|
||||
"cropDesc": "Набліжаць перадпрагляды да выбраных вобласцей фільтра замест паказу ўсяго кадра."
|
||||
},
|
||||
"subOnlyQuality": "У гэтым прамежку часу даступныя толькі запісы нізкай якасці"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@
|
||||
"copying": "Капіяванне",
|
||||
"encoding": "Кадаванне",
|
||||
"encodingRetry": "Кадаванне (паўтор)",
|
||||
"finalizing": "Завяршэнне",
|
||||
"merging": "Аб'яднанне"
|
||||
"finalizing": "Завяршэнне"
|
||||
},
|
||||
"caseView": {
|
||||
"noDescription": "Без апісання",
|
||||
|
||||
@@ -80,9 +80,9 @@
|
||||
"deletedFace_one": "Выдалены {{count}} твар.",
|
||||
"deletedFace_few": "Выдалена {{count}} твары.",
|
||||
"deletedFace_many": "Выдалена {{count}} твараў.",
|
||||
"deletedName_one": "{{count}} твар паспяхова выдалены.",
|
||||
"deletedName_few": "{{count}} твары паспяхова выдалены.",
|
||||
"deletedName_many": "{{count}} твараў паспяхова выдалена.",
|
||||
"deletedName_one": "Выдалены {{count}} твар.",
|
||||
"deletedName_few": "Выдалена {{count}} твары.",
|
||||
"deletedName_many": "Выдалена {{count}} твараў.",
|
||||
"renamedFace": "Твар перайменаваны на {{name}}",
|
||||
"trainedFace": "Твар навучаны.",
|
||||
"reclassifiedFace": "Твар перакласіфікаваны.",
|
||||
|
||||
@@ -6,12 +6,7 @@
|
||||
"lowBandwidthMode": "Рэжым нізкай паласы прапускання",
|
||||
"twoWayTalk": {
|
||||
"enable": "Уключыць двухбаковую размову",
|
||||
"disable": "Адключыць двухбаковую размову",
|
||||
"requiresWebRTC": "Двухбаковая размова патрабуе WebRTC, які недаступны",
|
||||
"error": {
|
||||
"microphone": "Двухбаковая размова не атрымала доступу да вашага мікрафона",
|
||||
"refused": "Не ўдалося пачаць двухбаковую размову. Падрабязнасці глядзіце ў кансолі браўзера."
|
||||
}
|
||||
"disable": "Адключыць двухбаковую размову"
|
||||
},
|
||||
"cameraAudio": {
|
||||
"enable": "Уключыць гук камеры",
|
||||
@@ -140,8 +135,7 @@
|
||||
"unavailable": "Для гэтай плыні гук недаступны"
|
||||
},
|
||||
"debug": {
|
||||
"picker": "Выбар плыні недаступны ў рэжыме адладкі. Адладачны выгляд заўсёды выкарыстоўвае плынь з роляй «detect».",
|
||||
"technology": "Выбар тэхналогіі трансляцыі недаступны ў рэжыме адладкі."
|
||||
"picker": "Выбар плыні недаступны ў рэжыме адладкі. Адладачны выгляд заўсёды выкарыстоўвае плынь з роляй «detect»."
|
||||
},
|
||||
"twoWayTalk": {
|
||||
"tips": "Ваша прылада мусіць падтрымліваць гэтую функцыю, а WebRTC мусіць быць наладжаны для двухбаковай размовы.",
|
||||
@@ -150,36 +144,11 @@
|
||||
},
|
||||
"lowBandwidth": {
|
||||
"tips": "Жывы прагляд працуе ў рэжыме нізкай паласы прапускання праз буферызацыю або памылкі плыні.",
|
||||
"resetStream": "Скінуць плынь",
|
||||
"force": {
|
||||
"label": "Прымусова ўключыць рэжым нізкай паласы прапускання",
|
||||
"desc": "Заўсёды прайграваць убудаваную ў Frigate плынь нізкай паласы прапускання замест выбранай. Працуе пры любым злучэнні, але мае ніжэйшую якасць і без гуку."
|
||||
}
|
||||
"resetStream": "Скінуць плынь"
|
||||
},
|
||||
"playInBackground": {
|
||||
"label": "Прайграваць у фоне",
|
||||
"tips": "Уключыце гэты параметр, каб плынь працягваўся, калі плэер схаваны."
|
||||
},
|
||||
"mode": "Тэхналогія трансляцыі",
|
||||
"technology": {
|
||||
"description": "Выберыце пажаданую тэхналогію трансляцыі. Пры памылках прайгравання ці сеткі Frigate усё роўна можа перайсці ў рэжым нізкай паласы прапускання.",
|
||||
"name": {
|
||||
"mse": "MSE",
|
||||
"webrtc": "WebRTC",
|
||||
"jsmpeg": "JSMpeg"
|
||||
},
|
||||
"tips": {
|
||||
"mse": "Рэкамендаваны прадвызначаны варыянт, шырокая сумяшчальнасць і плыўнае прайграванне",
|
||||
"webrtc": "Патрабуе дадатковай наладкі і падтрымліваецца не на кожнай прыладзе"
|
||||
},
|
||||
"unavailable": {
|
||||
"browser": "Ваш браўзер не падтрымлівае WebRTC.",
|
||||
"not-configured": "WebRTC не наладжаны. Задайце ў go2rtc webrtc candidates або ice_servers.",
|
||||
"unreachable": "WebRTC не змог злучыцца. Праверце, ці даступны порт 8555 і ці правільна зададзены серверы STUN/TURN.",
|
||||
"video-codec": "Відэакодэк гэтай плыні не падтрымліваецца WebRTC у гэтым браўзеры.",
|
||||
"audio-codec": "Аўдыякодэк гэтай плыні не падтрымліваецца WebRTC. Перакадуйце ў opus або G.711 праз go2rtc.",
|
||||
"checking": "Праверка даступнасці WebRTC…"
|
||||
}
|
||||
}
|
||||
},
|
||||
"cameraSettings": {
|
||||
|
||||
@@ -29,7 +29,7 @@
|
||||
"systemTelemetry": "Тэлеметрыя",
|
||||
"systemBirdseye": "Birdseye",
|
||||
"systemFfmpeg": "FFMPEG",
|
||||
"systemDetectorsAndModel": "Мадэлі дэтэктавання",
|
||||
"systemDetectorsAndModel": "Дэтэктары і мадэль",
|
||||
"systemMqtt": "MQTT",
|
||||
"systemGo2rtcStreams": "Плыні go2rtc",
|
||||
"integrationSemanticSearch": "Семантычны пошук",
|
||||
@@ -204,50 +204,11 @@
|
||||
"toast": {
|
||||
"success": {
|
||||
"clearStoredLayout": "Захаваная раскладка для {{cameraName}} ачышчана",
|
||||
"clearStreamingSettings": "Налады трансляцыі для ўсіх груп камер ачышчаны.",
|
||||
"exportUiSettings": "Налады экспартаваны",
|
||||
"importUiSettings": "Налады імпартаваны"
|
||||
"clearStreamingSettings": "Налады трансляцыі для ўсіх груп камер ачышчаны."
|
||||
},
|
||||
"error": {
|
||||
"clearStoredLayoutFailed": "Не ўдалося ачысціць захаваную раскладку: {{errorMessage}}",
|
||||
"clearStreamingSettingsFailed": "Не ўдалося ачысціць налады трансляцыі: {{errorMessage}}",
|
||||
"exportUiSettingsFailed": "Не ўдалося экспартаваць налады",
|
||||
"importNothingToApply": "Не ўдалося імпартаваць налады: файл не змяшчае налад",
|
||||
"importInvalidJson": "Не ўдалося імпартаваць налады: файл не з'яўляецца сапраўдным JSON",
|
||||
"importWrongType": "Не ўдалося імпартаваць налады: файл не з'яўляецца экспартам налад Frigate",
|
||||
"importUnsupportedVersion": "Не ўдалося імпартаваць налады: файлу патрэбна навейшая версія Frigate",
|
||||
"importInvalidSchema": "Не ўдалося імпартаваць налады: файл пашкоджаны",
|
||||
"importUiSettingsFailed": "Не ўдалося імпартаваць налады"
|
||||
}
|
||||
},
|
||||
"backupRestore": {
|
||||
"title": "Рэзервовая копія і аднаўленне",
|
||||
"transfer": {
|
||||
"label": "Файл налад прылады",
|
||||
"desc": "Раскладкі груп камер, налады трансляцыі і параметры інтэрфейсу захоўваюцца ў вашым браўзеры. Экспартуйце іх у файл, каб зрабіць рэзервовую копію або перанесці на іншую прыладу.",
|
||||
"export": "Экспартаваць налады",
|
||||
"import": "Імпартаваць налады"
|
||||
},
|
||||
"importDialog": {
|
||||
"title": "Імпартаваць налады",
|
||||
"desc": "Выберыце, што прымяніць з гэтага файла. Пасля імпарту Frigate перазагрузіцца.",
|
||||
"exportedFrom": "Экспартавана {{date}} з канфігурацыі Frigate версіі {{version}}",
|
||||
"layouts_one": "Раскладкі груп камер ({{count}} група)",
|
||||
"layouts_few": "Раскладкі груп камер ({{count}} групы)",
|
||||
"layouts_many": "Раскладкі груп камер ({{count}} груп)",
|
||||
"streaming_one": "Налады трансляцыі ({{count}} камера)",
|
||||
"streaming_few": "Налады трансляцыі ({{count}} камеры)",
|
||||
"streaming_many": "Налады трансляцыі ({{count}} камер)",
|
||||
"preferences_one": "Параметры інтэрфейсу ({{count}} налада)",
|
||||
"preferences_few": "Параметры інтэрфейсу ({{count}} налады)",
|
||||
"preferences_many": "Параметры інтэрфейсу ({{count}} налад)",
|
||||
"unknownGroups_one": "Групы камер {{groups}} няма на гэтым серверы. Яе налады захаваюцца, але не будуць выкарыстоўвацца.",
|
||||
"unknownGroups_few": "Груп камер {{groups}} няма на гэтым серверы. Іх налады захаваюцца, але не будуць выкарыстоўвацца.",
|
||||
"unknownGroups_many": "Груп камер {{groups}} няма на гэтым серверы. Іх налады захаваюцца, але не будуць выкарыстоўвацца.",
|
||||
"unknownCameras_one": "Камеры {{cameras}} няма на гэтым серверы. Яе налады трансляцыі будуць ігнаравацца.",
|
||||
"unknownCameras_few": "Камер {{cameras}} няма на гэтым серверы. Іх налады трансляцыі будуць ігнаравацца.",
|
||||
"unknownCameras_many": "Камер {{cameras}} няма на гэтым серверы. Іх налады трансляцыі будуць ігнаравацца.",
|
||||
"confirm": "Імпартаваць"
|
||||
"clearStreamingSettingsFailed": "Не ўдалося ачысціць налады трансляцыі: {{errorMessage}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -409,7 +370,7 @@
|
||||
}
|
||||
},
|
||||
"step3": {
|
||||
"description": "Наладзьце магчымасці і ролі плыняў, дадайце дадатковыя плыні для вашай камеры.",
|
||||
"description": "Наладзьце ролі плыняў і дадайце дадатковыя плыні для вашай камеры.",
|
||||
"streamsTitle": "Плыні камеры",
|
||||
"addStream": "Дадаць плынь",
|
||||
"addAnotherStream": "Дадаць яшчэ плынь",
|
||||
@@ -443,26 +404,11 @@
|
||||
"title": "Ролі плыняў",
|
||||
"detect": "Асноўная плынь для дэтэктавання аб'ектаў.",
|
||||
"record": "Захоўвае сегменты відэаплыні паводле налад канфігурацыі.",
|
||||
"audio": "Плынь для дэтэктавання па гуку.",
|
||||
"record_sub": "Запісы ніжэйшай якасці для адаптыўнага прайгравання і падоўжанага захоўвання (звычайна дадатковая плынь камеры)."
|
||||
"audio": "Плынь для дэтэктавання па гуку."
|
||||
},
|
||||
"featuresPopover": {
|
||||
"title": "Магчымасці плыні",
|
||||
"description": "Скарыстайцеся рэтрансляцыяй go2rtc, каб паменшыць колькасць падлучэнняў да камеры."
|
||||
},
|
||||
"appleCompatibility": {
|
||||
"title": "Палепшыць прайграванне на прыладах Apple",
|
||||
"description": "Уключыце, калі глядзіце запісы ў Safari або на iPhone, iPad ці Mac."
|
||||
},
|
||||
"ptz": {
|
||||
"title": "Уключыць кіраванне PTZ",
|
||||
"detectedNote": "Праз ONVIF выяўлена падтрымка PTZ. Калі гэта камера PTZ, з гэтым параметрам вы зможаце кіраваць паваротам, нахілам і маштабаваннем камеры з інтэрфейсу.",
|
||||
"connectionDetails": "Падрабязнасці злучэння ONVIF",
|
||||
"host": "Хост ONVIF",
|
||||
"port": "Порт ONVIF",
|
||||
"username": "Імя карыстальніка ONVIF",
|
||||
"password": "Пароль ONVIF",
|
||||
"hostRequiredWarning": "Калі ўключана кіраванне PTZ, патрэбны хост і порт ONVIF."
|
||||
}
|
||||
},
|
||||
"step4": {
|
||||
@@ -1489,9 +1435,7 @@
|
||||
"orphansDeleted": "Выдалена асірацелых",
|
||||
"aborted": "Перарвана. Выдаленне перавысіла б парог бяспекі.",
|
||||
"error": "Памылка",
|
||||
"totals": "Усяго",
|
||||
"spaceToReclaim": "Месца для вызвалення",
|
||||
"spaceReclaimed": "Вызвалена месца"
|
||||
"totals": "Усяго"
|
||||
},
|
||||
"event_snapshots": "Здымкі аб'ектаў пад адсочваннем",
|
||||
"event_thumbnails": "Паменшаныя выявы аб'ектаў пад адсочваннем",
|
||||
@@ -1544,12 +1488,7 @@
|
||||
},
|
||||
"knownPlates": {
|
||||
"namePlaceholder": "напрыклад Аўто жонкі",
|
||||
"platePlaceholder": "Нумар знака або рэгулярны выраз",
|
||||
"assignedTo": "Прызначана: {{name}}",
|
||||
"detected": "Выяўленыя нумарныя знакі",
|
||||
"noneDetected": "Нумарных знакаў пакуль не выяўлена",
|
||||
"search": "Знайдзіце або ўвядзіце нумарны знак",
|
||||
"useCustom": "Выкарыстаць «{{value}}»"
|
||||
"platePlaceholder": "Нумар знака або рэгулярны выраз"
|
||||
},
|
||||
"liveStreams": {
|
||||
"streamNameLabel": "Назва плыні",
|
||||
@@ -1605,8 +1544,7 @@
|
||||
"preset-record-mjpeg": "Запіс - камеры MJPEG",
|
||||
"preset-record-jpeg": "Запіс - камеры JPEG",
|
||||
"preset-record-ubiquiti": "Запіс - камеры Ubiquiti"
|
||||
},
|
||||
"sameAsRecord": "Тое самае, што выходныя аргументы запісу"
|
||||
}
|
||||
},
|
||||
"cameraInputs": {
|
||||
"itemTitle": "Плынь {{index}}",
|
||||
@@ -1691,11 +1629,8 @@
|
||||
"options": {
|
||||
"detect": "Дэтэктаваць",
|
||||
"record": "Запіс",
|
||||
"audio": "Аўдыя",
|
||||
"record_sub": "Запіс (дадатковая плынь)"
|
||||
},
|
||||
"roleInUse": "Ужо прызначана іншай плыні",
|
||||
"recordSubConflict": "Плынь не можа мець адначасова ролі record і record_sub"
|
||||
"audio": "Аўдыя"
|
||||
}
|
||||
},
|
||||
"genaiRoles": {
|
||||
"options": {
|
||||
@@ -1748,18 +1683,7 @@
|
||||
},
|
||||
"defaultRole": {
|
||||
"admin": "Адміністратар",
|
||||
"viewer": "Назіральнік",
|
||||
"none": "Няма (адмовіць у доступе)"
|
||||
},
|
||||
"birdseyeModes": {
|
||||
"summary": "Выбрана: {{count}}",
|
||||
"options": {
|
||||
"continuous": "Бесперапынна",
|
||||
"motion": "Рух",
|
||||
"all_objects": "Усе аб'екты",
|
||||
"alerts": "Абвесткі",
|
||||
"detections": "Дэтэктаванні"
|
||||
}
|
||||
"viewer": "Назіральнік"
|
||||
}
|
||||
},
|
||||
"globalConfig": {
|
||||
@@ -1981,8 +1905,7 @@
|
||||
"maxFramesSet": "Задаванне максімуму кадраў перавызначае прадвызначаныя паводзіны і адключае адсочванне нерухомых аб'ектаў. Гэта патрэбна вельмі рэдка, карыстайцеся асцярожна.",
|
||||
"squareResolution": "Квадратнае разрозненне дэтэктавання - незвычайны выбар. Шырыня і вышыня дэтэктавання мусяць адпавядаць фарматным суадносінам камеры (напрыклад 16:9), а не памерам мадэлі дэтэктавання аб'ектаў. Неадпаведнасць можа расцягнуць відарыс і знізіць дакладнасць дэтэктавання.",
|
||||
"resolutionHigh": "Гэта разрозненне дэтэктавання вышэйшае за рэкамендаванае і можа павялічыць спажыванне рэсурсаў без павышэння дакладнасці. Для большасці камер рэкамендуецца разрозненне не вышэй за 1080p.",
|
||||
"globalResolutionMultipleCameras": "Зададзена глабальнае разрозненне дэтэктавання, хоць наладжана некалькі камер. Калі камеры не маюць аднолькавых разрознення і фарматных суадносін, шырыню і вышыню дэтэктавання варта задаваць для кожнай камеры асобна.",
|
||||
"sceneWithoutModel": "Для гэтай сцэны не наладжана мадэль дэтэктавання, таму камера вяртаецца да мадэлі са сцэнай «All cameras». Дадайце мадэль для гэтай сцэны, каб камера мела сваю."
|
||||
"globalResolutionMultipleCameras": "Зададзена глабальнае разрозненне дэтэктавання, хоць наладжана некалькі камер. Калі камеры не маюць аднолькавых разрознення і фарматных суадносін, шырыню і вышыню дэтэктавання варта задаваць для кожнай камеры асобна."
|
||||
},
|
||||
"model": {
|
||||
"optimizedFor320": "Frigate аптымізаваны пад мадэль 320x320, і для большасці канфігурацый гэта найлепшы выбар. Мадэль 640x640 працуе павольней і дапамагае толькі ў асобных выпадках.",
|
||||
@@ -2006,8 +1929,7 @@
|
||||
"modelSizeLarge": "Мадэль «large» аптымізавана пад шматрадковыя нумарныя знакі. Мадэль «small» працуе хутчэй, і карыстацца варта ёй, калі ў вашым рэгіёне не ўжываюцца шматрадковыя знакі."
|
||||
},
|
||||
"record": {
|
||||
"noRecordRole": "Ніводнай плыні не прызначана роля «record». Запіс працаваць не будзе.",
|
||||
"noRecordSubRole": "Ні ў адной плыні не зададзена роля record_sub. Запіс дадатковай плыні не будзе працаваць."
|
||||
"noRecordRole": "Ніводнай плыні не прызначана роля «record». Запіс працаваць не будзе."
|
||||
},
|
||||
"snapshots": {
|
||||
"detectDisabled": "Дэтэктаванне аб'ектаў адключана. Здымкі ствараюцца з аб'ектаў пад адсочваннем і стварацца не будуць."
|
||||
@@ -2017,50 +1939,6 @@
|
||||
},
|
||||
"onvif": {
|
||||
"autotrackingNoZones": "Аўтаадсочванне патрабуе хаця б адной зоны. Вызначце зону для гэтай камеры ў раздзеле «Маскі і зоны», а потым пазначце яе як патрэбную ніжэй."
|
||||
},
|
||||
"birdseye": {
|
||||
"objectTrackingDetectDisabled": "Birdseye паказвае аб'екты пад адсочваннем, але дэтэктаванне аб'ектаў для гэтай камеры адключана. Камера не з'явіцца ў Birdseye."
|
||||
}
|
||||
},
|
||||
"detectionModels": {
|
||||
"title": "Мадэлі дэтэктавання",
|
||||
"description": "Наладзьце мадэлі дэтэктавання аб'ектаў і абсталяванне, на якім працуе кожная з іх. Камера выбірае мадэль паводле сваёй сцэны ў наладах дэтэктавання.",
|
||||
"addModel": "Дадаць мадэль",
|
||||
"cameras_one": "{{count}} камера",
|
||||
"cameras_few": "{{count}} камеры",
|
||||
"cameras_many": "{{count}} камер",
|
||||
"scene": {
|
||||
"label": "Сцэна",
|
||||
"description": "Асяроддзе, для якога прызначана гэтая мадэль. Камера выбірае мадэль, задаючы тую самую сцэну ў сваіх наладах дэтэктавання, а мадэль са сцэнай all выкарыстоўвае любая камера, якая нічога не задала."
|
||||
},
|
||||
"scenes": {
|
||||
"all": "Усе камеры",
|
||||
"indoor": "У памяшканні",
|
||||
"outdoor": "На вуліцы",
|
||||
"indoor_thermal": "У памяшканні, цеплавізійная",
|
||||
"outdoor_thermal": "На вуліцы, цеплавізійная"
|
||||
},
|
||||
"hardware": {
|
||||
"label": "Абсталяванне",
|
||||
"placeholder": "Выберыце абсталяванне",
|
||||
"loading": "Пошук абсталявання для дэтэктавання…",
|
||||
"none": "Абсталяванне не выбрана",
|
||||
"claimedBy": "выкарыстоўвае {{scene}}",
|
||||
"detectorCount": "Дэтэктары",
|
||||
"countRecommended_one": "Рэкамендуецца для {{count}} камеры",
|
||||
"countRecommended_few": "Рэкамендуецца для {{count}} камер",
|
||||
"countRecommended_many": "Рэкамендуецца для {{count}} камер",
|
||||
"unrecognized": "Гэтая мадэль наладжана для абсталявання, якога няма ў сістэме: {{devices}}",
|
||||
"description": "Абсталяванне, на якім гэтая мадэль выконвае дэтэктаванне.",
|
||||
"detectorCountDescription": "Колькі працэсаў дэтэктавання запускаць на гэтым абсталяванні. Большая колькасць дэтэктараў спраўляецца з большай колькасцю камер, але займае больш памяці прылады.",
|
||||
"unitsDescription": "Кожны блок выконвае свой працэс дэтэктавання. Блок, які ўжо выкарыстоўвае іншая мадэль, выбраць нельга."
|
||||
},
|
||||
"tabs": {
|
||||
"plus": "Frigate+",
|
||||
"custom": "Свая мадэль"
|
||||
},
|
||||
"plusModel": {
|
||||
"noModelSelected": "Выберыце мадэль Frigate+"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
"go2rtc": "Журналы go2rtc - Frigate",
|
||||
"nginx": "Журналы Nginx - Frigate",
|
||||
"websocket": "Журналы паведамленняў - Frigate"
|
||||
},
|
||||
"health": "Стан - Frigate"
|
||||
}
|
||||
},
|
||||
"title": "Сістэма",
|
||||
"metrics": "Сістэмныя метрыкі",
|
||||
@@ -149,10 +148,6 @@
|
||||
"unused": {
|
||||
"title": "Нявыкарыстана",
|
||||
"tips": "Гэта значэнне можа недакладна адлюстроўваць вольнае месца, даступнае Frigate, калі на дыску ёсць іншыя файлы акрамя запісаў Frigate. Frigate не адсочвае месца па-за сваімі запісамі."
|
||||
},
|
||||
"subStream": {
|
||||
"information": "Звесткі пра сховішча дадатковай плыні",
|
||||
"tips": "Камеры, якія пішуць дадатковую плынь, паказваюць выкарыстанне зыходнай і нізкай якасці асобна, тымі ж назвамі, што і параметры якасці пры прайграванні запісаў. Запісы нізкай якасці застаюцца на дыску да заканчэння тэрміну захоўвання, таму гэты падзел можа паказвацца і пасля таго, як запіс дадатковай плыні быў адключаны."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -186,11 +181,7 @@
|
||||
"segmentLength": "Даўжыня сегмента запісу:",
|
||||
"ok": "Ключавыя кадры прыблізна кожныя {{seconds}} с, гэта добра для запісу і прайгравання.",
|
||||
"unknown": "Не ўдалося вызначыць інтэрвал ключавых кадраў.",
|
||||
"recordDisabled": "Для гэтай камеры запіс адключаны.",
|
||||
"warningFixed": "Ключавыя кадры ідуць раўнамерна, але рэдка (прыкладна кожныя {{seconds}} с). Запіс працуе, але жывое прайграванне і перамотка пачынаюцца павольней. Задайце інтэрвал I-кадраў (ключавых кадраў) камеры роўным яе частаце кадраў.",
|
||||
"warningVariable": "Інтэрвал ключавых кадраў нераўнамерны (ад {{minSeconds}} с да {{maxSeconds}} с), што звычайна значыць уключаны разумны кодэк (H.264+/H.265+). Так рабіць не рэкамендуецца.",
|
||||
"errorFixed": "Ключавыя кадры кожныя прыкладна {{seconds}} с - гэта даўжэй за сегмент запісу ({{segmentTime}} с), таму некаторыя сегменты застаюцца без ключавога кадра і не будуць прайгравацца. Паменшыце інтэрвал I-кадраў (ключавых кадраў) камеры да яе частаты кадраў.",
|
||||
"errorVariable": "Прамежкі паміж ключавымі кадрамі дасягаюць прыкладна {{seconds}} с - гэта даўжэй за сегмент запісу ({{segmentTime}} с). Некаторыя сегменты застануцца без ключавога кадра, што ламае прайграванне. Адключыце разумны кодэк (+) на камеры або паменшыце інтэрвал ключавых кадраў."
|
||||
"recordDisabled": "Для гэтай камеры запіс адключаны."
|
||||
}
|
||||
},
|
||||
"framesAndDetections": "Кадры / дэтэктаванні",
|
||||
@@ -243,11 +234,7 @@
|
||||
"cameraIsOffline": "{{camera}} па-за сеткай",
|
||||
"detectIsSlow": "{{detect}} працуе павольна ({{speed}} мс)",
|
||||
"detectIsVerySlow": "{{detect}} працуе вельмі павольна ({{speed}} мс)",
|
||||
"debugReplayActive": "Сеанс адладачнага паўтору актыўны",
|
||||
"cameraSkippedDetections": "{{camera}} прапускае дэтэктаванне на {{pct}}% кадраў",
|
||||
"systemNotices_one": "{{count}} сістэмная заўвага",
|
||||
"systemNotices_other": "{{count}} сістэмнай заўвагі",
|
||||
"retentionUnmet": "Запісы выдаляюцца да заканчэння тэрміну захоўвання, каб вызваліць месца"
|
||||
"debugReplayActive": "Сеанс адладачнага паўтору актыўны"
|
||||
},
|
||||
"enrichments": {
|
||||
"title": "Узбагачэнні",
|
||||
@@ -275,93 +262,5 @@
|
||||
"classification_speed": "Хуткасць класіфікацыі {{name}}",
|
||||
"classification_events_per_second": "Падзей класіфікацыі {{name}} на секунду"
|
||||
}
|
||||
},
|
||||
"health": {
|
||||
"title": "Стан",
|
||||
"notices": {
|
||||
"title": "Заўвагі",
|
||||
"empty": "Ваша ўсталёўка Frigate у парадку",
|
||||
"dismiss": "Схаваць",
|
||||
"openSettings": "Адкрыць налады",
|
||||
"openLink": "Адкрыць спасылку",
|
||||
"noMatches": "Няма заўваг, якія адпавядаюць фільтру",
|
||||
"dismissedTitle": "Схаваныя",
|
||||
"noneDismissed": "Няма схаваных заўваг",
|
||||
"clearDismissed": "Ачысціць схаваныя",
|
||||
"clearDismissedTitle": "Ачысціць схаваныя заўвагі?",
|
||||
"clearDismissedDesc": "Усе схаваныя заўвагі будуць выдалены. Праверкі канфігурацыі і плыняў пакажуцца адразу, а іншыя заўвагі вернуцца пры наступным узнікненні.",
|
||||
"firstSeen_one": "Упершыню {{time}}",
|
||||
"firstSeen_other": "Упершыню {{time}} · {{count}} разу",
|
||||
"dismissedAt": "Схавана {{time}}",
|
||||
"filter": {
|
||||
"showDismissed": "Паказаць схаваныя",
|
||||
"severity": "Узровень важнасці",
|
||||
"error": "Памылка",
|
||||
"warning": "Папярэджанне",
|
||||
"info": "Звесткі"
|
||||
},
|
||||
"kinds": {
|
||||
"detector_stuck": "Дэтэктар {{detector}} перазапушчаны пасля таго, як перастаў адказваць",
|
||||
"model_download_failed": "Не ўдалося спампаваць {{file}} для {{model}}: {{error}}",
|
||||
"skipped_detections": "Дэтэктаванне не паспявала і больш за хвіліну прапускала {{pct}}% кадраў",
|
||||
"shm_too_low": "Выдзеленую памяць /dev/shm ({{total}} МБ) трэба павялічыць прынамсі да {{min}} МБ",
|
||||
"failed_login_one": "Няўдалая спроба ўваходу для {{user}}",
|
||||
"failed_login_other": "Няўдалыя спробы ўваходу для {{user}}",
|
||||
"update_available": "Даступная Frigate {{version}}"
|
||||
},
|
||||
"streamPrefix": "Плынь {{index}}: {{message}}",
|
||||
"streamPrefixRestream": "Плынь {{index}} (праз go2rtc): {{message}}",
|
||||
"streamProbeFailed": "Не ўдалося зандзіраваць плынь {{index}}: {{error}}",
|
||||
"cameraProbeFailed": "Не ўдалося зандзіраваць плыні: {{error}}"
|
||||
},
|
||||
"hardware": {
|
||||
"title": "Абсталяванне",
|
||||
"objectDetection": "Дэтэктаванне аб'ектаў",
|
||||
"hardwareAcceleration": "Апаратнае паскарэнне",
|
||||
"enrichments": {
|
||||
"title": "Узбагачэнні",
|
||||
"semantic_search": "Семантычны пошук",
|
||||
"face_recognition": "Распазнаванне асобы",
|
||||
"lpr": "Распазнаванне нумарных знакаў",
|
||||
"audio_transcription": "Транскрыпцыя гуку"
|
||||
},
|
||||
"cameraConnections": "Злучэнні камер",
|
||||
"allCamerasExcellent": "Усе камеры маюць выдатнае злучэнне.",
|
||||
"fps": "{{camera}} / {{expected}} fps",
|
||||
"nothingConfigured": "Нічога не наладжана",
|
||||
"allCameras": "Усе камеры",
|
||||
"probeUnavailable": "Выяўленне абсталявання недаступнае",
|
||||
"justStarted": "Frigate толькі што запусціўся",
|
||||
"deviceNotFound": "{{devices}} не знойдзена ў гэтай сістэме",
|
||||
"detectorNotRunning": "Працэс дэтэктара не запушчаны",
|
||||
"inferenceVerySlow": "Вывядзенне вельмі павольнае ({{speed}} мс)",
|
||||
"inferenceSlow": "Вывядзенне павольнае ({{speed}} мс)",
|
||||
"inferenceMs": "{{speed}} мс",
|
||||
"customArgs": "Свае аргументы ffmpeg",
|
||||
"customArgsNotVerified": "Свае аргументы ffmpeg, не правераныя",
|
||||
"hwaccelNotConfigured": "Апаратнае дэкадаванне не выкарыстоўваецца, хоць {{family}} даступнае. Выберыце яго ў наладах ffmpeg",
|
||||
"hwaccelHardwareMissing": "{{family}} наладжана, але апаратнае зандзіраванне яго не выявіла",
|
||||
"unrecognizedDevice": "Нераспазнанае перавызначэнне прылады, не праверана",
|
||||
"decoderUsage": "дэкадавальнік {{usage}}",
|
||||
"remoteProvider": "Аддалены правайдар",
|
||||
"acceleratorMissing": "Наладжана для {{device}}, але сумяшчальнага паскаральніка не знойдзена",
|
||||
"modelNotRunYet": "Мадэль яшчэ не запускалася, прылада правяраецца пасля першага выкарыстання",
|
||||
"fellBackToCpu": "Наладжана для {{device}}, але працуе на CPU",
|
||||
"cpuDespiteAccelerator": "Працуе на CPU, хоць паскаральнік даступны",
|
||||
"probed": "Зандзіравана",
|
||||
"probing": "Зандзіраванне…",
|
||||
"recheck": "Праверыць абсталяванне зноў",
|
||||
"cameraStreams": "Плыні камер",
|
||||
"streamsNotChecked": "Яшчэ не правяралася",
|
||||
"streamsChecking": "Правярае {{done}} з {{total}}",
|
||||
"streamsClean": "Праблем з плынямі няма",
|
||||
"checked": "Праверана",
|
||||
"runAgain": "Запусціць зноў",
|
||||
"runStreamChecks": "Запусціць праверку плыняў",
|
||||
"streamsChecked_one": "{{count}} камера правераная",
|
||||
"streamsChecked_other": "{{count}} камеры правераных",
|
||||
"streamsFlagged_one": "{{count}} з праблемамі, пералічана ў Заўвагах",
|
||||
"streamsFlagged_other": "{{count}} з праблемамі, пералічана ў Заўвагах"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
{
|
||||
"noPreviewFoundFor": "Не е намерен предварителен преглед за {{cameraName}}",
|
||||
"stats": {
|
||||
"latency": {
|
||||
"short": {
|
||||
"value": "{{seconds}} сек",
|
||||
"title": "Закъснение"
|
||||
},
|
||||
"title": "Закъснение:",
|
||||
"value": "{{seconds}} секунди"
|
||||
},
|
||||
"streamType": {
|
||||
"title": "Тип поток:",
|
||||
"short": "Тип"
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
"title": "Širina pojasa:",
|
||||
"short": "Širina pojasa"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Kasnjenje:",
|
||||
"value": "{{seconds}} sekundi",
|
||||
"short": {
|
||||
"title": "Kasnjenje",
|
||||
"value": "{{seconds}} sek"
|
||||
}
|
||||
},
|
||||
"totalFrames": "Ukupno okvira:",
|
||||
"droppedFrames": {
|
||||
"title": "Izgubljeni okviri:",
|
||||
|
||||
@@ -55,9 +55,9 @@
|
||||
"be": "Беларуская (belarús)"
|
||||
},
|
||||
"system": "Sistema",
|
||||
"systemMetrics": "Salut i Mètriques",
|
||||
"systemMetrics": "Mètriques del sistema",
|
||||
"configuration": "Configuració",
|
||||
"systemLogs": "Registres",
|
||||
"systemLogs": "Registres del sistema",
|
||||
"configurationEditor": "Editor de configuració",
|
||||
"languages": "Idiomes",
|
||||
"settings": "Opcions",
|
||||
@@ -287,10 +287,7 @@
|
||||
"savingAll": "S'està desant tot…",
|
||||
"undoAll": "Desfés-ho tot",
|
||||
"applying": "S'està aplicant…",
|
||||
"retry": "Torna a intentar",
|
||||
"expand": "Expandeix",
|
||||
"collapse": "Redueix",
|
||||
"reload": "Torna a carregar"
|
||||
"retry": "Torna a intentar"
|
||||
},
|
||||
"toast": {
|
||||
"copyUrlToClipboard": "URL copiada al porta-retalls.",
|
||||
@@ -331,36 +328,5 @@
|
||||
"validation_errors": "Errors de validació",
|
||||
"credentialField": {
|
||||
"savedPlaceholder": "Desat — deixa en blanc per mantenir l'actual"
|
||||
},
|
||||
"error": {
|
||||
"title": "Aquesta pàgina ha deixat de funcionar",
|
||||
"desc": "La pàgina ha tingut un error inesperat. La recàrrega normalment la neteja. Si continua passant, copieu els detalls i adjunteu-los a una discussió sobre GitHub.",
|
||||
"staleTitle": "Recàrrega requerida",
|
||||
"staleDesc": "No s'ha pogut carregar part de la interfície, cosa que normalment significa que Frigate s'ha actualitzat mentre aquesta pestanya estava oberta. Torna a carregar per a recollir la nova versió.",
|
||||
"partial": "Part de la interfície va deixar de funcionar.",
|
||||
"copyDetails": "Copia els detalls",
|
||||
"copyFailed": "No s'han pogut copiar els detalls al porta-retalls"
|
||||
},
|
||||
"commandMenu": {
|
||||
"title": "Menú d'ordres",
|
||||
"description": "Cerca pàgines, càmeres, paràmetres i accions",
|
||||
"placeholder": "Cerca pàgines, càmeres, paràmetres i accions",
|
||||
"empty": "Sense coincidències",
|
||||
"hint": "{{key}} o / per obrir, Intro per executar",
|
||||
"section": {
|
||||
"recent": "Recent",
|
||||
"pages": "Pàg",
|
||||
"cameras": "Càmeres",
|
||||
"cameraGroups": "Grups de càmera",
|
||||
"settings": "Configuració",
|
||||
"actions": "Accions"
|
||||
},
|
||||
"camera": {
|
||||
"live": "Directe",
|
||||
"review": "Revisió"
|
||||
},
|
||||
"action": {
|
||||
"toggleTheme": "Commuta el mode clar i fosc"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -137,15 +137,6 @@
|
||||
"partial": "S'han iniciat {{successful}} de {{total}} exportacions. Ha fallat: {{failedItems}}",
|
||||
"failed": "No s'han pogut iniciar {{total}} exportacions. Ha fallat: {{failedItems}}"
|
||||
}
|
||||
},
|
||||
"stream": {
|
||||
"label": "Qualitat",
|
||||
"auto": "Automàtic",
|
||||
"main": "Original",
|
||||
"sub": "Baix",
|
||||
"autoDesc": "Utilitza el flux principal i torna al flux de menor qualitat quan el principal no està disponible.",
|
||||
"mainDesc": "Exporta només el flux principal de qualitat original. Faltaran els intervals de temps on el flux principal no està disponible.",
|
||||
"subDesc": "Exporta només el subflux de menor qualitat. Faltaran els intervals de temps on el subflux no està disponible."
|
||||
}
|
||||
},
|
||||
"streaming": {
|
||||
@@ -181,8 +172,7 @@
|
||||
"deleteNow": "Suprimir ara",
|
||||
"export": "Exportar",
|
||||
"markAsReviewed": "Marcar com a revisat",
|
||||
"markAsUnreviewed": "Marcar com no revisat",
|
||||
"generateDescription": "Genera la descripció"
|
||||
"markAsUnreviewed": "Marcar com no revisat"
|
||||
},
|
||||
"confirmDelete": {
|
||||
"title": "Confirmar la supressió",
|
||||
@@ -201,12 +191,6 @@
|
||||
"custom": "Marca horària personalitzada",
|
||||
"button": "Comparteix l'URL de la marca horària",
|
||||
"shareTitle": "Marca de temps de revisió de Frigate: {{camera}}"
|
||||
},
|
||||
"genaiDescription": {
|
||||
"toast": {
|
||||
"success": "S'ha sol·licitat una descripció de IA Generativa per a aquest element de revisió.",
|
||||
"error": "No s'ha pogut sol·licitar la descripció: {{error}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imagePicker": {
|
||||
|
||||
@@ -1,5 +1,13 @@
|
||||
{
|
||||
"stats": {
|
||||
"latency": {
|
||||
"short": {
|
||||
"title": "Latència",
|
||||
"value": "{{seconds}} s"
|
||||
},
|
||||
"title": "Latència:",
|
||||
"value": "{{seconds}} segons"
|
||||
},
|
||||
"streamType": {
|
||||
"title": "Tipus de transmissió:",
|
||||
"short": "Tipus"
|
||||
@@ -37,23 +45,8 @@
|
||||
"submittedFrigatePlus": "Fotograma enviat correctament a Frigate+"
|
||||
},
|
||||
"error": {
|
||||
"submitFrigatePlusFailed": "Error al enviar fotograma a Frigate+",
|
||||
"playRecordingsFailed": "No s'han pogut reproduir els enregistraments (error {{code}}): {{message}}"
|
||||
"submitFrigatePlusFailed": "Error al enviar fotograma a Frigate+"
|
||||
}
|
||||
},
|
||||
"cameraOff": "La càmera està apagada",
|
||||
"quality": {
|
||||
"auto": "Automàtic",
|
||||
"autoLow": "Reproduint de baixa qualitat (ample de banda limitat)",
|
||||
"autoLowCodec": "Reproducció de baixa qualitat (Original no suportat per aquest navegador)",
|
||||
"autoLowSaveData": "Reproducció de baixa qualitat (desador de dades)",
|
||||
"main": "Original",
|
||||
"sub": "Baixa",
|
||||
"notSupportedBrowser": "No és compatible amb aquest navegador",
|
||||
"label": "Qualitat",
|
||||
"noAudio": "Sense àudio",
|
||||
"audioRate": "{{rate}} àudio kHz",
|
||||
"audioCodecRate": "{{codec}} {{rate}} kHz",
|
||||
"noRecordings": "No hi ha enregistraments en aquest interval de temps"
|
||||
}
|
||||
"cameraOff": "La càmera està apagada"
|
||||
}
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
"num_threads": {
|
||||
"label": "Fils de detecció",
|
||||
"description": "Nombre de fils a utilitzar per al processament de detecció d'àudio."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "Personalització del mapa d'etiquetes d'àudio",
|
||||
"description": "Sobreescriu o reassigna les entrades per a fusionar-se en el mapa d'etiquetes d'àudio estàndard."
|
||||
}
|
||||
},
|
||||
"audio_transcription": {
|
||||
@@ -77,10 +73,6 @@
|
||||
"order": {
|
||||
"label": "Posició",
|
||||
"description": "Posició numèrica que controla l'ordenació de la càmera en la disposició Birdseye."
|
||||
},
|
||||
"modes": {
|
||||
"label": "Tipus d'activitat",
|
||||
"description": "Tipus d'activitat que inclouen càmeres a Birdseye."
|
||||
}
|
||||
},
|
||||
"detect": {
|
||||
@@ -141,10 +133,6 @@
|
||||
"annotation_offset": {
|
||||
"label": "Desplaçament de l'anotació",
|
||||
"description": "Mil·lisegons per a desplaçar detecta anotacions per a alinear millor els límits de la línia de temps amb els enregistraments; pot ser positiu o negatiu."
|
||||
},
|
||||
"scene": {
|
||||
"label": "Detecta l'escena",
|
||||
"description": "L'entorn que mira aquesta càmera, utilitzat per triar quin dels models configurats s'executa en ell. Les càmeres que queden a 'totes' executen el model configurat amb una escena de 'totes'."
|
||||
}
|
||||
},
|
||||
"face_recognition": {
|
||||
@@ -188,10 +176,6 @@
|
||||
"record": {
|
||||
"label": "Registra els arguments de sortida",
|
||||
"description": "Arguments de sortida predeterminats per a enregistrar fluxos de rols."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "Arguments de sortida del registre de subflux",
|
||||
"description": "Arguments de sortida per als fluxos de rols record.sub. Els arguments de sortida del registre s'utilitzen quan no s'estableix."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
@@ -372,51 +356,51 @@
|
||||
"label": "Màscara en brut"
|
||||
},
|
||||
"genai": {
|
||||
"label": "Configuració de l'objecte IA Generativa",
|
||||
"description": "Opcions d'IA Generativa per descriure objectes rastrejats i enviar fotogrames per a la generació.",
|
||||
"label": "Configuració de l'objecte GenAI",
|
||||
"description": "Opcions de GenAI per descriure objectes rastrejats i enviar fotogrames per a la generació.",
|
||||
"enabled": {
|
||||
"label": "Habilita l'IA Generativa",
|
||||
"description": "Habilita la generació de descripcions d'IA Generativa per als objectes rastrejats de manera predeterminada."
|
||||
"label": "Habilita el GenAI",
|
||||
"description": "Habilita la generació de descripcions de GenAI per als objectes rastrejats de manera predeterminada."
|
||||
},
|
||||
"use_snapshot": {
|
||||
"label": "Utilitza instantànies",
|
||||
"description": "Usa instantànies d'objecte en lloc de miniatures per a la generació de descripcions d'IA Generativa."
|
||||
"description": "Usa instantànies d'objecte en lloc de miniatures per a la generació de descripcions de GenAI."
|
||||
},
|
||||
"prompt": {
|
||||
"label": "Indicació de la llegenda",
|
||||
"description": "Plantilla de pregunta predeterminada utilitzada en generar descripcions amb IA Generativa."
|
||||
"description": "Plantilla de pregunta predeterminada utilitzada en generar descripcions amb GenAI."
|
||||
},
|
||||
"object_prompts": {
|
||||
"label": "Peticions d'objecte",
|
||||
"description": "Per objecte demana personalitzar les sortides d'IA Generativa per a etiquetes específiques."
|
||||
"description": "Per objecte demana personalitzar les sortides de GenAI per a etiquetes específiques."
|
||||
},
|
||||
"objects": {
|
||||
"label": "Objectes d'IA Generativa",
|
||||
"description": "Llista d'etiquetes d'objectes a enviar a IA Generativa per defecte."
|
||||
"label": "Objectes GenAI",
|
||||
"description": "Llista d'etiquetes d'objectes a enviar a GenAI per defecte."
|
||||
},
|
||||
"required_zones": {
|
||||
"label": "Zones requerides",
|
||||
"description": "Zones que s'han d'introduir perquè els objectes es puguin classificar per a la generació de descripcions d'IA Generativa."
|
||||
"description": "Zones que s'han d'introduir perquè els objectes es puguin classificar per a la generació de descripcions de GenAI."
|
||||
},
|
||||
"debug_save_thumbnails": {
|
||||
"label": "Desa les miniatures",
|
||||
"description": "Desa les miniatures enviades a IA Generativa per a la depuració i la revisió."
|
||||
"description": "Desa les miniatures enviades a GenAI per a la depuració i la revisió."
|
||||
},
|
||||
"send_triggers": {
|
||||
"label": "Activadors d'IA Generativa",
|
||||
"description": "Defineix quan s'han d'enviar fotogrames a IA Generativa (al final, després de les actualitzacions, etc.).",
|
||||
"label": "Activadors de GenAI",
|
||||
"description": "Defineix quan s'han d'enviar fotogrames a GenAI (al final, després de les actualitzacions, etc.).",
|
||||
"tracked_object_end": {
|
||||
"label": "Envia al final",
|
||||
"description": "Envia una sol·licitud a IA Generativa quan acabi l'objecte rastrejat."
|
||||
"description": "Envia una sol·licitud a GenAI quan acabi l'objecte rastrejat."
|
||||
},
|
||||
"after_significant_updates": {
|
||||
"label": "Activador d'IA Generativa primerenc",
|
||||
"description": "Envia una sol·licitud a IA Generativa després d'un nombre especificat d'actualitzacions significatives per a l'objecte rastrejat."
|
||||
"label": "Activador de GenAI primerenc",
|
||||
"description": "Envia una sol·licitud a GenAI després d'un nombre especificat d'actualitzacions significatives per a l'objecte rastrejat."
|
||||
}
|
||||
},
|
||||
"enabled_in_config": {
|
||||
"label": "Estat original d'IA Generativa",
|
||||
"description": "Indica si l'IA Generativa s'ha activat a la configuració estàtica original."
|
||||
"label": "Estat original de GenAI",
|
||||
"description": "Indica si el GenAI s'ha activat a la configuració estàtica original."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -521,59 +505,11 @@
|
||||
"enabled_in_config": {
|
||||
"label": "Estat de l'enregistrament original",
|
||||
"description": "Indica si l'enregistrament s'ha activat en la configuració estàtica original."
|
||||
},
|
||||
"sub": {
|
||||
"label": "Enregistrament de subflux",
|
||||
"description": "Paràmetres per a enregistrar un segon flux de menor qualitat.",
|
||||
"enabled": {
|
||||
"label": "Habilita l'enregistrament de subflux",
|
||||
"description": "Permet l'enregistrament d'un segon flux de menor qualitat per a la reproducció de qualitat adaptativa i la retenció estesa."
|
||||
},
|
||||
"continuous": {
|
||||
"label": "Retenció contínua del subflux",
|
||||
"description": "Nombre de dies per a retenir els enregistraments de sub flux independentment dels objectes o el moviment seguits.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Dies per retenir enregistraments."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "Retenció del moviment del subflux",
|
||||
"description": "Nombre de dies per a retenir els enregistraments de substream activats pel moviment.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Dies per retenir enregistraments."
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"label": "Retenció d'alertes del subflux",
|
||||
"description": "Paràmetres de retenció per als enregistraments de substream d'alertes.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Nombre de dies per a retenir enregistraments d'esdeveniments de detecció."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Mode de retenció",
|
||||
"description": "Mode de retenció: tot (desa tots els segments), moviment (desa els segments amb moviment), o actiuobobjectes (desa els segments amb objectes actius)."
|
||||
}
|
||||
},
|
||||
"detections": {
|
||||
"label": "Retenció de la detecció de subflux",
|
||||
"description": "Paràmetres de retenció per als enregistraments de substream de les deteccions.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Nombre de dies per a retenir enregistraments d'esdeveniments de detecció."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Mode de retenció",
|
||||
"description": "Mode de retenció: tot (desa tots els segments), moviment (desa els segments amb moviment), o actiuobobjectes (desa els segments amb objectes actius)."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"label": "Revisió",
|
||||
"description": "Configuració que controla les alertes, les deteccions i els resums de revisió d'IA Generativa utilitzats per la interfície d'usuari i l'emmagatzematge d'aquesta càmera.",
|
||||
"description": "Configuració que controla les alertes, les deteccions i els resums de revisió de GenAI utilitzats per la interfície d'usuari i l'emmagatzematge d'aquesta càmera.",
|
||||
"alerts": {
|
||||
"label": "Configuració d'alertes",
|
||||
"description": "Paràmetres per als quals els objectes rastrejats generen alertes i com es mantenen les alertes",
|
||||
@@ -623,51 +559,43 @@
|
||||
}
|
||||
},
|
||||
"genai": {
|
||||
"label": "Configuració de l'IA Generativa",
|
||||
"description": "Controla l'ús de l'IA generativa per a la producció de descripcions i resums d'elements de revisió.",
|
||||
"label": "Configuració del GenAI",
|
||||
"description": "Controla l'ús de la IA generativa per a la producció de descripcions i resums d'elements de revisió.",
|
||||
"enabled": {
|
||||
"label": "Habilita les descripcions de l'IA Generativa",
|
||||
"description": "Activa o desactiva les descripcions i resums generats per IA Generativa per als elements de revisió."
|
||||
"label": "Habilita les descripcions del GenAI",
|
||||
"description": "Activa o desactiva les descripcions i resums generats per GenAI per als elements de revisió."
|
||||
},
|
||||
"alerts": {
|
||||
"label": "Habilita l'IA Generativa per a alertes",
|
||||
"description": "Utilitzeu IA Generativa per a generar descripcions per als elements d'alerta."
|
||||
"label": "Habilita el GenAI per a alertes",
|
||||
"description": "Utilitzeu GenAI per a generar descripcions per als elements d'alerta."
|
||||
},
|
||||
"detections": {
|
||||
"label": "Habilita l'IA Generativa per a les deteccions",
|
||||
"description": "Utilitzeu IA Generativa per generar descripcions per als elements de detecció."
|
||||
"label": "Habilita el GenAI per a les deteccions",
|
||||
"description": "Utilitzeu GenAI per generar descripcions per als elements de detecció."
|
||||
},
|
||||
"image_source": {
|
||||
"label": "Revisa l'origen de la imatge",
|
||||
"description": "Font d'imatges enviades a IA Generativa ('previsualització' o 'enregistraments'); 'enregistraments' utilitza Fotogrames de més qualitat però més tokens."
|
||||
"description": "Font d'imatges enviades a GenAI ('previsualització' o 'enregistraments'); 'enregistraments' utilitza Fotogrames de més qualitat però més tokens."
|
||||
},
|
||||
"additional_concerns": {
|
||||
"label": "Altres preocupacions",
|
||||
"description": "Una llista de preocupacions o notes addicionals que l¡IA Generativa ha de tenir en compte a l'hora d'avaluar l'activitat en aquesta càmera."
|
||||
"description": "Una llista de preocupacions o notes addicionals que el GenAI ha de tenir en compte a l'hora d'avaluar l'activitat en aquesta càmera."
|
||||
},
|
||||
"debug_save_thumbnails": {
|
||||
"label": "Desa les miniatures",
|
||||
"description": "Desa les miniatures que s'envien al proveïdor IA Generativa per a la depuració i la revisió."
|
||||
"description": "Desa les miniatures que s'envien al proveïdor GenAI per a la depuració i la revisió."
|
||||
},
|
||||
"enabled_in_config": {
|
||||
"label": "Estat original d'IA Generativa",
|
||||
"description": "Fa un seguiment de si la revisió d'IA Generativa es va habilitar originalment a la configuració estàtica."
|
||||
"label": "Estat original de GenAI",
|
||||
"description": "Fa un seguiment de si la revisió de GenAI es va habilitar originalment a la configuració estàtica."
|
||||
},
|
||||
"preferred_language": {
|
||||
"label": "Idioma preferit",
|
||||
"description": "Idioma preferit per sol·licitar al proveïdor d'IA Generativa respostes generades."
|
||||
"description": "Idioma preferit per sol·licitar al proveïdor GenAI respostes generades."
|
||||
},
|
||||
"activity_context_prompt": {
|
||||
"label": "Indicador de context de l'activitat",
|
||||
"description": "Pregunta personalitzada que descriu el que és i no és una activitat sospitosa per proporcionar context per als resums de GenAI."
|
||||
},
|
||||
"response_style": {
|
||||
"label": "Estil de resposta",
|
||||
"description": "Escriviu un predefinit d'estil per a les descripcions generades de les revisions. Els valors predefinits ajusten el to i el nivell de detall del títol orientat a l'usuari, el resum i la descripció de l'escena; «predeterminat» deixa l'indicatiu incorporat sense canvis."
|
||||
},
|
||||
"frame_mode": {
|
||||
"label": "Mode de fotograma",
|
||||
"description": "Com es presenten els marcs al model. Els 'frames' envien l'indicatiu seguit pels fotogrames, que s'adapta als models que segueixen una seqüència per si sols. 'annotated.frames' etiqueta cada marc i entrellaça notes derivades del seguiment d'objectes, el que ajuda als models que perden el rastre de l'activitat que es repeteix o reverteix."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -31,10 +31,6 @@
|
||||
"record": {
|
||||
"label": "Registra els arguments de sortida",
|
||||
"description": "Arguments de sortida predeterminats per a enregistrar fluxos de rols."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "Arguments de sortida del registre de subflux",
|
||||
"description": "Arguments de sortida per als fluxos de rols record.sub. Els arguments de sortida del registre s'utilitzen quan no s'estableix."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
@@ -197,49 +193,49 @@
|
||||
"genai": {
|
||||
"required_zones": {
|
||||
"label": "Zones requerides",
|
||||
"description": "Zones que s'han d'introduir perquè els objectes es puguin classificar per a la generació de descripcions d'IA Generativa."
|
||||
"description": "Zones que s'han d'introduir perquè els objectes es puguin classificar per a la generació de descripcions de GenAI."
|
||||
},
|
||||
"label": "Configuració de l'objecte IA Generativa",
|
||||
"description": "Opcions d'IA Generativa per descriure objectes rastrejats i enviar fotogrames per a la generació.",
|
||||
"label": "Configuració de l'objecte GenAI",
|
||||
"description": "Opcions de GenAI per descriure objectes rastrejats i enviar fotogrames per a la generació.",
|
||||
"enabled": {
|
||||
"label": "Habilita l'IA Generativa",
|
||||
"description": "Habilita la generació de descripcions d'IA Generativa per als objectes rastrejats de manera predeterminada."
|
||||
"label": "Habilita el GenAI",
|
||||
"description": "Habilita la generació de descripcions de GenAI per als objectes rastrejats de manera predeterminada."
|
||||
},
|
||||
"use_snapshot": {
|
||||
"label": "Utilitza instantànies",
|
||||
"description": "Usa instantànies d'objecte en lloc de miniatures per a la generació de descripcions d'IA Generativa."
|
||||
"description": "Usa instantànies d'objecte en lloc de miniatures per a la generació de descripcions de GenAI."
|
||||
},
|
||||
"prompt": {
|
||||
"label": "Indicació de la llegenda",
|
||||
"description": "Plantilla de pregunta predeterminada utilitzada en generar descripcions amb IA Generativa."
|
||||
"description": "Plantilla de pregunta predeterminada utilitzada en generar descripcions amb GenAI."
|
||||
},
|
||||
"object_prompts": {
|
||||
"label": "Peticions d'objecte",
|
||||
"description": "Per objecte demana personalitzar les sortides d'IA Generativa per a etiquetes específiques."
|
||||
"description": "Per objecte demana personalitzar les sortides de GenAI per a etiquetes específiques."
|
||||
},
|
||||
"objects": {
|
||||
"label": "Objectes d'IA Generativa",
|
||||
"description": "Llista d'etiquetes d'objectes a enviar a IA Generativa per defecte."
|
||||
"label": "Objectes GenAI",
|
||||
"description": "Llista d'etiquetes d'objectes a enviar a GenAI per defecte."
|
||||
},
|
||||
"debug_save_thumbnails": {
|
||||
"label": "Desa les miniatures",
|
||||
"description": "Desa les miniatures enviades a IA Generativa per a la depuració i la revisió."
|
||||
"description": "Desa les miniatures enviades a GenAI per a la depuració i la revisió."
|
||||
},
|
||||
"send_triggers": {
|
||||
"label": "Activadors d'IA Generativa",
|
||||
"description": "Defineix quan s'han d'enviar fotogrames a IA Generativa (al final, després de les actualitzacions, etc.).",
|
||||
"label": "Activadors de GenAI",
|
||||
"description": "Defineix quan s'han d'enviar fotogrames a GenAI (al final, després de les actualitzacions, etc.).",
|
||||
"tracked_object_end": {
|
||||
"label": "Envia al final",
|
||||
"description": "Envia una sol·licitud a IA Generativa quan acabi l'objecte rastrejat."
|
||||
"description": "Envia una sol·licitud a GenAI quan acabi l'objecte rastrejat."
|
||||
},
|
||||
"after_significant_updates": {
|
||||
"label": "Activador d'IA Generativa primerenc",
|
||||
"description": "Envia una sol·licitud a IA Generativa després d'un nombre especificat d'actualitzacions significatives per a l'objecte rastrejat."
|
||||
"label": "Activador de GenAI primerenc",
|
||||
"description": "Envia una sol·licitud a GenAI després d'un nombre especificat d'actualitzacions significatives per a l'objecte rastrejat."
|
||||
}
|
||||
},
|
||||
"enabled_in_config": {
|
||||
"label": "Estat original d'IA Generativa",
|
||||
"description": "Indica si l'IA Generativa s'ha activat a la configuració estàtica original."
|
||||
"label": "Estat original de GenAI",
|
||||
"description": "Indica si el GenAI s'ha activat a la configuració estàtica original."
|
||||
}
|
||||
},
|
||||
"label": "Objectes",
|
||||
@@ -392,54 +388,6 @@
|
||||
"enabled_in_config": {
|
||||
"label": "Estat de l'enregistrament original",
|
||||
"description": "Indica si l'enregistrament s'ha activat en la configuració estàtica original."
|
||||
},
|
||||
"sub": {
|
||||
"label": "Enregistrament de subflux",
|
||||
"description": "Paràmetres per a enregistrar un segon flux de menor qualitat.",
|
||||
"enabled": {
|
||||
"label": "Habilita l'enregistrament de subflux",
|
||||
"description": "Permet l'enregistrament d'un segon flux de menor qualitat per a la reproducció de qualitat adaptativa i la retenció estesa."
|
||||
},
|
||||
"continuous": {
|
||||
"label": "Retenció contínua del subflux",
|
||||
"description": "Nombre de dies per a retenir els enregistraments de sub flux independentment dels objectes o el moviment seguits.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Dies per retenir enregistraments."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "Retenció del moviment del subflux",
|
||||
"description": "Nombre de dies per a retenir els enregistraments de substream activats pel moviment.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Dies per retenir enregistraments."
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"label": "Retenció d'alertes del subflux",
|
||||
"description": "Paràmetres de retenció per als enregistraments de substream d'alertes.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Nombre de dies per a retenir enregistraments d'esdeveniments de detecció."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Mode de retenció",
|
||||
"description": "Mode de retenció: tot (desa tots els segments), moviment (desa els segments amb moviment), o actiuobobjectes (desa els segments amb objectes actius)."
|
||||
}
|
||||
},
|
||||
"detections": {
|
||||
"label": "Retenció de la detecció de subflux",
|
||||
"description": "Paràmetres de retenció per als enregistraments de substream de les deteccions.",
|
||||
"days": {
|
||||
"label": "Dies de retenció",
|
||||
"description": "Nombre de dies per a retenir enregistraments d'esdeveniments de detecció."
|
||||
},
|
||||
"mode": {
|
||||
"label": "Mode de retenció",
|
||||
"description": "Mode de retenció: tot (desa tots els segments), moviment (desa els segments amb moviment), o actiuobobjectes (desa els segments amb objectes actius)."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
@@ -469,50 +417,42 @@
|
||||
},
|
||||
"genai": {
|
||||
"image_source": {
|
||||
"description": "Font d'imatges enviades a IA Generativa ('previsualització' o 'enregistraments'); 'enregistraments' utilitza Fotogrames de més qualitat però més tokens.",
|
||||
"description": "Font d'imatges enviades a GenAI ('previsualització' o 'enregistraments'); 'enregistraments' utilitza Fotogrames de més qualitat però més tokens.",
|
||||
"label": "Revisa l'origen de la imatge"
|
||||
},
|
||||
"enabled_in_config": {
|
||||
"description": "Fa un seguiment de si la revisió d'IA Generativa es va habilitar originalment a la configuració estàtica.",
|
||||
"label": "Estat original d'IA Generativa"
|
||||
"description": "Fa un seguiment de si la revisió de GenAI es va habilitar originalment a la configuració estàtica.",
|
||||
"label": "Estat original de GenAI"
|
||||
},
|
||||
"label": "Configuració de l'IA Generativa",
|
||||
"description": "Controla l'ús de l'IA generativa per a la producció de descripcions i resums d'elements de revisió.",
|
||||
"label": "Configuració del GenAI",
|
||||
"description": "Controla l'ús de la IA generativa per a la producció de descripcions i resums d'elements de revisió.",
|
||||
"enabled": {
|
||||
"label": "Habilita les descripcions de l'IA Generativa",
|
||||
"description": "Activa o desactiva les descripcions i resums generats per IA Generativa per als elements de revisió."
|
||||
"label": "Habilita les descripcions del GenAI",
|
||||
"description": "Activa o desactiva les descripcions i resums generats per GenAI per als elements de revisió."
|
||||
},
|
||||
"alerts": {
|
||||
"label": "Habilita l'IA Generativa per a alertes",
|
||||
"description": "Utilitzeu IA Generativa per a generar descripcions per als elements d'alerta."
|
||||
"label": "Habilita el GenAI per a alertes",
|
||||
"description": "Utilitzeu GenAI per a generar descripcions per als elements d'alerta."
|
||||
},
|
||||
"detections": {
|
||||
"label": "Habilita l'IA Generativa per a les deteccions",
|
||||
"description": "Utilitzeu IA Generativa per generar descripcions per als elements de detecció."
|
||||
"label": "Habilita el GenAI per a les deteccions",
|
||||
"description": "Utilitzeu GenAI per generar descripcions per als elements de detecció."
|
||||
},
|
||||
"additional_concerns": {
|
||||
"label": "Altres preocupacions",
|
||||
"description": "Una llista de preocupacions o notes addicionals que l¡IA Generativa ha de tenir en compte a l'hora d'avaluar l'activitat en aquesta càmera."
|
||||
"description": "Una llista de preocupacions o notes addicionals que el GenAI ha de tenir en compte a l'hora d'avaluar l'activitat en aquesta càmera."
|
||||
},
|
||||
"debug_save_thumbnails": {
|
||||
"label": "Desa les miniatures",
|
||||
"description": "Desa les miniatures que s'envien al proveïdor IA Generativa per a la depuració i la revisió."
|
||||
"description": "Desa les miniatures que s'envien al proveïdor GenAI per a la depuració i la revisió."
|
||||
},
|
||||
"preferred_language": {
|
||||
"label": "Idioma preferit",
|
||||
"description": "Idioma preferit per sol·licitar al proveïdor d'IA Generativa respostes generades."
|
||||
"description": "Idioma preferit per sol·licitar al proveïdor GenAI respostes generades."
|
||||
},
|
||||
"activity_context_prompt": {
|
||||
"label": "Indicador de context de l'activitat",
|
||||
"description": "Pregunta personalitzada que descriu el que és i no és una activitat sospitosa per proporcionar context per als resums de GenAI."
|
||||
},
|
||||
"response_style": {
|
||||
"label": "Estil de resposta",
|
||||
"description": "Escriviu un predefinit d'estil per a les descripcions generades de les revisions. Els valors predefinits ajusten el to i el nivell de detall del títol orientat a l'usuari, el resum i la descripció de l'escena; «predeterminat» deixa l'indicatiu incorporat sense canvis."
|
||||
},
|
||||
"frame_mode": {
|
||||
"label": "Mode de fotograma",
|
||||
"description": "Com es presenten els marcs al model. Els 'frames' envien l'indicatiu seguit pels fotogrames, que s'adapta als models que segueixen una seqüència per si sols. 'annotated.frames' etiqueta cada marc i entrellaça notes derivades del seguiment d'objectes, el que ajuda als models que perden el rastre de l'activitat que es repeteix o reverteix."
|
||||
}
|
||||
},
|
||||
"label": "Revisió",
|
||||
@@ -759,7 +699,7 @@
|
||||
"description": "Configuració per a la transcripció d'àudio en viu i de veu utilitzada per a esdeveniments i llegendes en directe.",
|
||||
"language": {
|
||||
"label": "Idioma de transcripció",
|
||||
"description": "Codi d'idioma utilitzat per a la transcripció/traducció (per exemple 'en' per a l'anglès), o 'auto' per permetre que el model el detecti. Vegeu https://whisper-api.com/docs/languages/ per als codis de llengua compatibles."
|
||||
"description": "Codi d'idioma utilitzat per a la transcripció/traducció (per exemple 'en' per a l'anglès). Vegeu https://whisper-api.com/docs/languages/ per als codis de llengua compatibles."
|
||||
},
|
||||
"device": {
|
||||
"label": "Dispositiu de transcripció",
|
||||
@@ -772,10 +712,6 @@
|
||||
"live_enabled": {
|
||||
"label": "Transcripció en viu",
|
||||
"description": "Habilita la transcripció en directe per a l'àudio a mesura que es rep."
|
||||
},
|
||||
"model": {
|
||||
"label": "Model de transcripció d'àudio o nom del proveïdor GenAI",
|
||||
"description": "El dorsal de transcripció: 'whisper' per als models locals integrats de Frigate, o el nom d'un proveïdor de GenAI amb el rol de transcriure."
|
||||
}
|
||||
},
|
||||
"version": {
|
||||
@@ -1035,7 +971,7 @@
|
||||
},
|
||||
"default_role": {
|
||||
"label": "Rol predeterminat",
|
||||
"description": "Rol predeterminat assignat als usuaris intermediaris autenticats quan no s'aplica cap mapatge de rols. Establiu-ho a «none» per a denegar l'accés als usuaris sense mapar."
|
||||
"description": "Rol predeterminat assignat als usuaris intermediaris autenticats quan no s'aplica cap mapatge de rols."
|
||||
},
|
||||
"separator": {
|
||||
"label": "Caràcter separador",
|
||||
@@ -1083,7 +1019,7 @@
|
||||
}
|
||||
},
|
||||
"genai": {
|
||||
"label": "Configuració de l'IA Generativa",
|
||||
"label": "Configuració de la IA generada",
|
||||
"description": "Paràmetres per als proveïdors integrats generatius d'IA utilitzats per generar descripcions d'objectes i resums de revisions.",
|
||||
"api_key": {
|
||||
"label": "Clau API",
|
||||
@@ -1099,15 +1035,15 @@
|
||||
},
|
||||
"provider": {
|
||||
"label": "Proveïdor",
|
||||
"description": "El proveïdor IA Generativa a utilitzar (per exemple: ollama, gemini, openai)."
|
||||
"description": "El proveïdor GenAI a utilitzar (per exemple: ollama, gemini, openai)."
|
||||
},
|
||||
"roles": {
|
||||
"label": "Rols",
|
||||
"description": "Rols d'IA Generativa (xat, descripcions, incrustacions, transcriure); un proveïdor per rol. Per defecte només es concedeixen xats, descripcions i incrustacions; la transcripció s'ha de llistar explícitament."
|
||||
"description": "Rols de GenAI (xat, descripcions, incrustacions); un proveïdor per rol."
|
||||
},
|
||||
"provider_options": {
|
||||
"label": "Opcions del proveïdor",
|
||||
"description": "Opcions addicionals específiques del proveïdor per passar al client d'IA Generativa."
|
||||
"description": "Opcions addicionals específiques del proveïdor per passar al client GenAI."
|
||||
},
|
||||
"runtime_options": {
|
||||
"label": "Opcions de temps d'execució",
|
||||
@@ -1148,10 +1084,6 @@
|
||||
"num_threads": {
|
||||
"label": "Fils de detecció",
|
||||
"description": "Nombre de fils a utilitzar per al processament de detecció d'àudio."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "Personalització del mapa d'etiquetes d'àudio",
|
||||
"description": "Sobreescriu o reassigna les entrades per a fusionar-se en el mapa d'etiquetes d'àudio estàndard."
|
||||
}
|
||||
},
|
||||
"birdseye": {
|
||||
@@ -1200,11 +1132,7 @@
|
||||
"label": "Posició",
|
||||
"description": "Posició numèrica que controla l'ordenació de la càmera en la disposició Birdseye."
|
||||
},
|
||||
"label": "Birdseye",
|
||||
"modes": {
|
||||
"label": "Tipus d'activitat",
|
||||
"description": "Tipus d'activitat que inclouen càmeres a Birdseye."
|
||||
}
|
||||
"label": "Birdseye"
|
||||
},
|
||||
"detect": {
|
||||
"label": "Detecció d'objectes",
|
||||
@@ -1264,10 +1192,6 @@
|
||||
"annotation_offset": {
|
||||
"label": "Desplaçament de l'anotació",
|
||||
"description": "Mil·lisegons per a desplaçar detecta anotacions per a alinear millor els límits de la línia de temps amb els enregistraments; pot ser positiu o negatiu."
|
||||
},
|
||||
"scene": {
|
||||
"label": "Detecta l'escena",
|
||||
"description": "L'entorn que mira aquesta càmera, utilitzat per triar quin dels models configurats s'executa en ell. Les càmeres que queden a 'totes' executen el model configurat amb una escena de 'totes'."
|
||||
}
|
||||
},
|
||||
"classification": {
|
||||
@@ -1475,57 +1399,5 @@
|
||||
"active_profile": {
|
||||
"label": "Perfil actiu",
|
||||
"description": "Nom de perfil actualment actiu. Només en temps d'execució, no ha persistit en YAML."
|
||||
},
|
||||
"models": {
|
||||
"label": "Models de detecció",
|
||||
"description": "Models de detecció d'objectes i el maquinari en què s'executa. Les càmeres trien un model fent coincidir el seu detect.scene amb l'escena d'un model.",
|
||||
"scene": {
|
||||
"label": "Escena del model",
|
||||
"description": "L'entorn de la càmera per al qual s'utilitza aquest model. Les càmeres seleccionen un model establint detect.scene a un valor coincident, i «all» és utilitzat per qualsevol càmera que no n'estableixi un."
|
||||
},
|
||||
"devices": {
|
||||
"label": "hardware de detecció",
|
||||
"description": "Aquest model funciona com a '<detector>' o '<detector>:<device>' (per exemple 'edgetpu:pci:0' o 'openvino:GPU'). La llista del mateix dispositiu més d'una vegada executa processos d'inferència addicionals."
|
||||
},
|
||||
"path": {
|
||||
"label": "Ruta del model de detector d'objectes personalitzat",
|
||||
"description": "Ruta a un fitxer de model de detecció personalitzat (o plus://<model_id> per a models Frigate+)."
|
||||
},
|
||||
"labelmap_path": {
|
||||
"label": "Mapa d'etiquetes per al detector d'objectes personalitzat",
|
||||
"description": "Ruta a un fitxer de mapa d'etiquetes que assigna classes numèriques a etiquetes de cadena per al detector."
|
||||
},
|
||||
"width": {
|
||||
"label": "Amplada d'entrada del model de detecció d'objectes",
|
||||
"description": "Amplada del tensor d'entrada del model en píxels."
|
||||
},
|
||||
"height": {
|
||||
"label": "Alçada d'entrada del model de detecció d'objectes",
|
||||
"description": "Alçada del tensor d'entrada del model en píxels."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "Personalització del mapa d'etiquetes",
|
||||
"description": "Sobreescriu o reassigna les entrades per a fusionar-se en el mapa d'etiquetes estàndard."
|
||||
},
|
||||
"attributes_map": {
|
||||
"label": "Mapa d'etiquetes d'objectes a les seves etiquetes d'atribut",
|
||||
"description": "Assignació des d'etiquetes d'objectes a etiquetes d'atribut utilitzades per adjuntar metadades (per exemple 'cotxe' -). ['matricula'])."
|
||||
},
|
||||
"input_tensor": {
|
||||
"label": "Forma del sensor d'entrada del model",
|
||||
"description": "Format del sensor esperat pel model: 'nhwc' o 'nchw'."
|
||||
},
|
||||
"input_pixel_format": {
|
||||
"label": "Format de color del píxel d'entrada del model",
|
||||
"description": "Espai de color del píxel esperat pel model: 'rgb', 'bgr' o 'yuv'."
|
||||
},
|
||||
"input_dtype": {
|
||||
"label": "Tipus D d'entrada del model",
|
||||
"description": "Tipus de dades del tensor d'entrada del model (per exemple «float32»)."
|
||||
},
|
||||
"model_type": {
|
||||
"label": "Tipus de model de detecció d'objectes",
|
||||
"description": "Tipus d'arquitectura del model de detector (ssd, yolox, yolonas, yolo-generic, rfdetr, dfine) utilitzat per alguns detectors per a l'optimització."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,5 @@
|
||||
},
|
||||
"detect": {
|
||||
"dimensionMustBeEven": "Ha de ser un nombre parell."
|
||||
},
|
||||
"models": {
|
||||
"defaultRequired": "Un model ha d'utilitzar una escena de \"Totes les càmeres\". Sense ella, qualsevol càmera que no esculli una escena no té cap model al qual tornar."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,6 @@
|
||||
"auto_scroll": {
|
||||
"title": "Desplaçament automàtic",
|
||||
"desc": "Segueix els missatges nous a mesura que arriben."
|
||||
},
|
||||
"always_allow": {
|
||||
"title": "Accions sempre permeses",
|
||||
"desc": "Accions que l'assistent pot executar sense preguntar primer.",
|
||||
"none": "Cap",
|
||||
"reset": "Restableix"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
@@ -74,15 +68,5 @@
|
||||
},
|
||||
"thinking": {
|
||||
"toggle": "Commuta el pensament"
|
||||
},
|
||||
"approval": {
|
||||
"title": "Aprova {{tool}}?",
|
||||
"desc": "Aquesta acció canvia alguna cosa a Frigate. Revisa els detalls abans d'aprovar.",
|
||||
"approve": "Aprova",
|
||||
"always_allow": "Permet sempre",
|
||||
"reject": "Rebutja",
|
||||
"approved": "Aprovat",
|
||||
"rejected": "Rebutjat",
|
||||
"placeholder": "Aprova o rebutja l'acció pendent de continuar"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,5 @@
|
||||
"crop": "Escapça per filtrar",
|
||||
"cropAria": "Commuta la vista prèvia d'escapçament a les àrees filtrades",
|
||||
"cropDesc": "Amplia les vistes prèvies a les àrees de filtre seleccionades en lloc de mostrar el fotograma complet."
|
||||
},
|
||||
"subOnlyQuality": "Només els enregistraments de baixa qualitat estan disponibles en aquest interval de temps"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,8 +63,7 @@
|
||||
"copying": "Copiant",
|
||||
"encoding": "Codificant",
|
||||
"encodingRetry": "Codificant (reintent)",
|
||||
"finalizing": "Finalitzant",
|
||||
"merging": "Fusió"
|
||||
"finalizing": "Finalitzant"
|
||||
},
|
||||
"caseView": {
|
||||
"noDescription": "Sense descripció",
|
||||
|
||||
@@ -50,12 +50,7 @@
|
||||
"lowBandwidthMode": "Mode de baix ample de banda",
|
||||
"twoWayTalk": {
|
||||
"enable": "Activa la comunicació bidireccional",
|
||||
"disable": "Desactiva la comunicació bidireccional",
|
||||
"requiresWebRTC": "La conversa en dues direccions requereix WebRTC, que no està disponible",
|
||||
"error": {
|
||||
"microphone": "La conversa en dues direccions no ha pogut accedir al micròfon",
|
||||
"refused": "No s'ha pogut iniciar la conversa en dues direccions. Consulteu la consola del navegador per a més detalls."
|
||||
}
|
||||
"disable": "Desactiva la comunicació bidireccional"
|
||||
},
|
||||
"cameraAudio": {
|
||||
"enable": "Habilitar l'àudio de la càmera",
|
||||
@@ -132,40 +127,14 @@
|
||||
},
|
||||
"lowBandwidth": {
|
||||
"resetStream": "Restablir transmissió",
|
||||
"tips": "La vista en directe està en mode de baix ample de banda a causa d'errors de transmissió o de buffering.",
|
||||
"force": {
|
||||
"label": "Força el mode d'amplada de banda baixa",
|
||||
"desc": "Reprodueix sempre el canal d'amplada de banda baixa integrat per Frigate en lloc del flux seleccionat. Funciona en qualsevol connexió, però té menor qualitat i sense àudio."
|
||||
}
|
||||
"tips": "La vista en directe està en mode de baix ample de banda a causa d'errors de transmissió o de buffering."
|
||||
},
|
||||
"playInBackground": {
|
||||
"label": "Reproduir en segon pla",
|
||||
"tips": "Habilita aquesta opció per a contiuar la transmissió tot i que el reproductor estigui ocult."
|
||||
},
|
||||
"debug": {
|
||||
"picker": "Selecció de stream no disponible en mode debug. La vista debug sempre fa servir el stream assignat pel rol de detecció.",
|
||||
"technology": "La selecció de la tecnologia de flux no està disponible en el mode de depuració."
|
||||
},
|
||||
"mode": "Tecnologia Streaming",
|
||||
"technology": {
|
||||
"description": "Tria la teva tecnologia de streaming preferida. Frigate encara pot tornar al mode d'amplada de banda baixa en la reproducció o els errors de xarxa.",
|
||||
"tips": {
|
||||
"mse": "Predeterminada recomanada, compatibilitat àmplia i reproducció suau",
|
||||
"webrtc": "Necessita configuració addicional i no està suportat en tots els dispositius"
|
||||
},
|
||||
"unavailable": {
|
||||
"browser": "El teu navegador no suporta WebRTC.",
|
||||
"not-configured": "WebRTC no està configurat. Estableix candidats go2rtc webrtc o ice_servers.",
|
||||
"unreachable": "WebRTC no s'ha pogut connectar. Comproveu que el port 8555 és accessible i qualsevol servidor STUN/TURN és correcte.",
|
||||
"video-codec": "El còdec de vídeo d'aquest flux no és compatible amb WebRTC en aquest navegador.",
|
||||
"audio-codec": "El còdec d'àudio d'aquest flux no és compatible amb WebRTC. Transcodifica a opus o G.711 amb go2rtc.",
|
||||
"checking": "S'està comprovant la disponibilitat de WebRTC…"
|
||||
},
|
||||
"name": {
|
||||
"mse": "MSE",
|
||||
"webrtc": "WebRTC",
|
||||
"jsmpeg": "JSMpeg"
|
||||
}
|
||||
"picker": "Selecció de stream no disponible en mode debug. La vista debug sempre fa servir el stream assignat pel rol de detecció."
|
||||
}
|
||||
},
|
||||
"streamingSettings": "Paràmetres de transmissió",
|
||||
|
||||
@@ -88,7 +88,7 @@
|
||||
"uiSettings": "Paràmetres de la IU",
|
||||
"profiles": "Perfils",
|
||||
"systemGo2rtcStreams": "go2rtc streams",
|
||||
"systemDetectorsAndModel": "Models de detecció"
|
||||
"systemDetectorsAndModel": "Detectors i model"
|
||||
},
|
||||
"dialog": {
|
||||
"unsavedChanges": {
|
||||
@@ -150,50 +150,11 @@
|
||||
"toast": {
|
||||
"success": {
|
||||
"clearStoredLayout": "Disposició emmagatzemada esborrada per {{cameraName}}",
|
||||
"clearStreamingSettings": "S'han suprimit els paràmetres de la transmissió per tots els grups de càmeres.",
|
||||
"exportUiSettings": "Configuració exportada",
|
||||
"importUiSettings": "Configuració importada"
|
||||
"clearStreamingSettings": "S'han suprimit els paràmetres de la transmissió per tots els grups de càmeres."
|
||||
},
|
||||
"error": {
|
||||
"clearStoredLayoutFailed": "Error en suprimir la disposició desada: {{errorMessage}}",
|
||||
"clearStreamingSettingsFailed": "Error en esborrar els paràmetres de la transmissió: {{errorMessage}}",
|
||||
"exportUiSettingsFailed": "No s'han pogut exportar els paràmetres",
|
||||
"importNothingToApply": "No s'ha pogut importar la configuració: el fitxer no conté cap configuració",
|
||||
"importInvalidJson": "No s'ha pogut importar la configuració: el fitxer no és un JSON vàlid",
|
||||
"importWrongType": "Ha fallat la importació de la configuració: el fitxer no és una exportació de la configuració de Frigate",
|
||||
"importUnsupportedVersion": "No s'ha pogut importar la configuració: el fitxer requereix una versió més nova de Frigate",
|
||||
"importInvalidSchema": "No s'ha pogut importar la configuració: el fitxer està mal format",
|
||||
"importUiSettingsFailed": "No s'han pogut importar els paràmetres"
|
||||
}
|
||||
},
|
||||
"backupRestore": {
|
||||
"title": "Còpia de seguretat i restauració",
|
||||
"transfer": {
|
||||
"label": "Fitxer de configuració del dispositiu",
|
||||
"desc": "Les disposicions del grup de càmeres, la configuració de la transmissió i les preferències de la interfície d'usuari s'emmagatzemen al vostre navegador. Exporta-les a un fitxer per fer-ne una còpia de seguretat o per moure-les a un altre dispositiu.",
|
||||
"export": "Exporta la configuració",
|
||||
"import": "Importa els paràmetres"
|
||||
},
|
||||
"importDialog": {
|
||||
"title": "Importa els paràmetres",
|
||||
"desc": "Trieu què aplicar d'aquest fitxer. Frigate es tornarà a carregar quan acabi la importació.",
|
||||
"exportedFrom": "S'ha exportat {{date}} de la versió de configuració de Frigate {{version}}",
|
||||
"layouts_one": "Distribucions de grup de càmeres (grup{{count}})",
|
||||
"layouts_many": "Distribucions de grup de càmera ({{count}} grups)",
|
||||
"layouts_other": "Distribucions de grup de càmera ({{count}} grups)",
|
||||
"streaming_one": "Configuració de l'Streaming (càmera {{count}})",
|
||||
"streaming_many": "Configuració de l'Streaming (càmeres {{count}})",
|
||||
"streaming_other": "Configuració de l'Streaming (càmeres {{count}})",
|
||||
"preferences_one": "Preferències de la interfície d'usuari (ajust {{count}})",
|
||||
"preferences_many": "Preferències de la interfície d'usuari ( {{count}} paràmetres)",
|
||||
"preferences_other": "Preferències de la interfície d'usuari ( {{count}} paràmetres)",
|
||||
"unknownGroups_one": "El grup de càmeres {{groups}} no és en aquest servidor. La seva configuració es desarà però no s'utilitzarà.",
|
||||
"unknownGroups_many": "Els grups de càmeres {{groups}} no són en aquest servidor. La seva configuració es desarà però no s'utilitzarà.",
|
||||
"unknownGroups_other": "Els grups de càmeres {{groups}} no són en aquest servidor. La seva configuració es desarà però no s'utilitzarà.",
|
||||
"unknownCameras_one": "La càmera {{cameras}} no és en aquest servidor. S'ignorarà la seva configuració de transmissió.",
|
||||
"unknownCameras_many": "Les càmeres {{cameras}} no són en aquest servidor. S'ignoraran els seus paràmetres de transmissió.",
|
||||
"unknownCameras_other": "Les càmeres {{cameras}} no són en aquest servidor. S'ignoraran els seus paràmetres de transmissió.",
|
||||
"confirm": "Importa"
|
||||
"clearStreamingSettingsFailed": "Error en esborrar els paràmetres de la transmissió: {{errorMessage}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1063,7 +1024,7 @@
|
||||
}
|
||||
},
|
||||
"step3": {
|
||||
"description": "Configura característiques, rols de flux i afegeix fluxos addicionals per a la càmera.",
|
||||
"description": "Configura els rols de flux i afegeix fluxos addicionals per a la càmera.",
|
||||
"streamTitle": "Flux {{number}}",
|
||||
"roles": "Rols",
|
||||
"streamsTitle": "Fluxos de la càmera",
|
||||
@@ -1097,26 +1058,11 @@
|
||||
"title": "Roles de flux",
|
||||
"detect": "Canal principal per a la detecció d'objectes.",
|
||||
"record": "Desa els segments del canal de vídeo basats en la configuració.",
|
||||
"audio": "Canal per a la detecció basada en àudio.",
|
||||
"record_sub": "Enregistraments de menor qualitat per a la reproducció adaptativa i la retenció estesa (típicament el substream de la càmera)."
|
||||
"audio": "Canal per a la detecció basada en àudio."
|
||||
},
|
||||
"featuresPopover": {
|
||||
"title": "Característiques del flux",
|
||||
"description": "Utilitzeu el restreaming go2rtc per reduir les connexions a la càmera."
|
||||
},
|
||||
"appleCompatibility": {
|
||||
"title": "Millora la reproducció en dispositius Apple",
|
||||
"description": "Activeu això si mireu enregistraments al Safari o a un iPhone, iPad o Mac."
|
||||
},
|
||||
"ptz": {
|
||||
"title": "Habilita els controls PTZ",
|
||||
"detectedNote": "S'ha detectat suport PTZ a través de l'ONVIF. Si es tracta d'una càmera PTZ, habilitar aquesta opció us permetrà controlar les funcions pan/tilt/zoom de la càmera des de la interfície d'usuari.",
|
||||
"connectionDetails": "Detalls de la connexió ONVIF",
|
||||
"host": "Amfitrió ONVIF",
|
||||
"port": "Port ONVIF",
|
||||
"username": "Nom d'usuari ONVIF",
|
||||
"password": "Contrasenya ONVIF",
|
||||
"hostRequiredWarning": "Es requereix un amfitrió i un port ONVIF quan s'habiliten els controls PTZ."
|
||||
}
|
||||
},
|
||||
"step4": {
|
||||
@@ -1447,9 +1393,7 @@
|
||||
"orphansDeleted": "Orfes eliminats",
|
||||
"aborted": "Avortat. La supressió superaria el llindar de seguretat.",
|
||||
"error": "Error",
|
||||
"totals": "Totals",
|
||||
"spaceToReclaim": "Espai a reclamar",
|
||||
"spaceReclaimed": "Espai reclamat"
|
||||
"totals": "Totals"
|
||||
},
|
||||
"event_snapshots": "Instantànies de l'objecte rastrejat",
|
||||
"event_thumbnails": "Miniatures d'objecte rastrejat",
|
||||
@@ -1545,8 +1489,7 @@
|
||||
"preset-record-mjpeg": "Registre - Càmeres MJPEG",
|
||||
"preset-record-jpeg": "Registre - Càmeres JPEG",
|
||||
"preset-record-ubiquiti": "Registre - Càmeres Ubiquiti"
|
||||
},
|
||||
"sameAsRecord": "Igual que els arguments de sortida del registre"
|
||||
}
|
||||
},
|
||||
"cameraInputs": {
|
||||
"itemTitle": "Flux {{index}}",
|
||||
@@ -1627,11 +1570,8 @@
|
||||
"options": {
|
||||
"detect": "Detecta",
|
||||
"record": "Enregistrament",
|
||||
"audio": "Àudio",
|
||||
"record_sub": "Registre (Sub Flux)"
|
||||
},
|
||||
"roleInUse": "Ja assignat a un altre flux",
|
||||
"recordSubConflict": "Un flux no pot tenir els rols record andsub"
|
||||
"audio": "Àudio"
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
"title": "Configuració de la revisió"
|
||||
@@ -1653,8 +1593,7 @@
|
||||
"options": {
|
||||
"embeddings": "Vectors",
|
||||
"descriptions": "Descripcions",
|
||||
"chat": "Xat",
|
||||
"transcribe": "Transcripció"
|
||||
"chat": "Xat"
|
||||
}
|
||||
},
|
||||
"semanticSearchModel": {
|
||||
@@ -1679,12 +1618,7 @@
|
||||
},
|
||||
"knownPlates": {
|
||||
"namePlaceholder": "per exemple. Cotxe de la parella",
|
||||
"platePlaceholder": "Matricula o regex",
|
||||
"assignedTo": "Assignat a {{name}}",
|
||||
"detected": "Plaques detectades",
|
||||
"noneDetected": "Encara no s'ha detectat cap matrícula",
|
||||
"search": "Cerca o introdueix una matrícula",
|
||||
"useCustom": "Utilitza \"{{value}}\""
|
||||
"platePlaceholder": "Matricula o regex"
|
||||
},
|
||||
"semanticSearchModelSize": {
|
||||
"notApplicable": "No aplicable als proveïdors de GenAI"
|
||||
@@ -1709,26 +1643,7 @@
|
||||
},
|
||||
"defaultRole": {
|
||||
"admin": "Administrar",
|
||||
"viewer": "Visor",
|
||||
"none": "Cap (denega l'accés)"
|
||||
},
|
||||
"birdseyeModes": {
|
||||
"summary": "{{count}} seleccionats",
|
||||
"options": {
|
||||
"continuous": "Continu",
|
||||
"motion": "Moviment",
|
||||
"all_objects": "Tots els objectes",
|
||||
"alerts": "Alertes",
|
||||
"detections": "Deteccions"
|
||||
}
|
||||
},
|
||||
"audioTranscriptionModel": {
|
||||
"placeholder": "Selecciona el model…",
|
||||
"builtIn": "Models integrats",
|
||||
"genaiProviders": "Proveïdors de GenAI"
|
||||
},
|
||||
"audioTranscriptionModelSize": {
|
||||
"notApplicable": "No aplicable als proveïdors de GenAI"
|
||||
"viewer": "Visor"
|
||||
}
|
||||
},
|
||||
"globalConfig": {
|
||||
@@ -1800,10 +1715,7 @@
|
||||
"overriddenBaseConfigHeading_one": "El perfil {{profile}} substitueix el camp {{count}} de la configuració base:",
|
||||
"overriddenBaseConfigHeading_many": "El perfil {{profile}} substitueix {{count}} camps de la configuració base:",
|
||||
"overriddenBaseConfigHeading_other": "El perfil {{profile}} substitueix {{count}} camps de la configuració base:",
|
||||
"overriddenBaseConfigNoDeltas": "El perfil {{profile}} substitueix aquesta secció, però no hi ha valors de camp diferents de la configuració base.",
|
||||
"overriddenLive": "Sobreescrit (Viure)",
|
||||
"overriddenLiveTooltip": "Aquesta càmera s'està executant amb un valor diferent del desat a la configuració, que es mostra aquí. La vista en viu, MQTT, o un perfil actiu pot canviar-la mentre s'està executant Frigate.",
|
||||
"overriddenLiveValue": "Valor en execució: {{value}}"
|
||||
"overriddenBaseConfigNoDeltas": "El perfil {{profile}} substitueix aquesta secció, però no hi ha valors de camp diferents de la configuració base."
|
||||
},
|
||||
"profiles": {
|
||||
"title": "Perfils",
|
||||
@@ -1921,18 +1833,13 @@
|
||||
"recordDisabled": "L'enregistrament està desactivat, els elements de revisió no es generaran.",
|
||||
"detectDisabled": "La detecció d'objectes està desactivada. Els elements de revisió requereixen objectes detectats per categoritzar alertes i deteccions.",
|
||||
"allNonAlertDetections": "Totes les activitats que no siguin alertes s'inclouran com a deteccions.",
|
||||
"genaiImageSourceRecordingsRecordDisabled": "La font d'imatges està configurada com a 'enregistraments', però l'enregistrament està desactivat. Frigate tornarà a la vista prèvia de les imatges.",
|
||||
"recordRuntimeDisabled": "L'enregistrament està activat a la configuració, però actualment està desactivat per a aquesta càmera, de manera que els elements de revisió no es generaran. Torneu-lo a activar des de la vista en viu de la càmera, o comproveu si un perfil actiu l'està desactivant.",
|
||||
"detectRuntimeDisabled": "La detecció d'objectes està activada a la configuració, però actualment està desactivada per a aquesta càmera. Els elements de revisió requereixen objectes detectats per categoritzar alertes i deteccions. Torneu-lo a activar des de la vista en viu de la càmera, o comproveu si un perfil actiu l'està desactivant.",
|
||||
"genaiImageSourceRecordingsRecordRuntimeDisabled": "La font d'imatges està configurada com a 'enregistraments', però l'enregistrament està desactivat per a aquesta càmera tot i que la configuració l'habilita. Frigate tornarà a la vista prèvia de les imatges."
|
||||
"genaiImageSourceRecordingsRecordDisabled": "La font d'imatges està configurada com a 'enregistraments', però l'enregistrament està desactivat. Frigate tornarà a la vista prèvia de les imatges."
|
||||
},
|
||||
"audio": {
|
||||
"noAudioRole": "Cap flux té definit el rol d'àudio. Heu d'habilitar el rol d'àudio per a la detecció d'àudio perquè funcioni."
|
||||
},
|
||||
"audioTranscription": {
|
||||
"audioDetectionDisabled": "La detecció d'àudio no està activada per a aquesta càmera. La transcripció d'àudio requereix que la detecció d'àudio estigui activa.",
|
||||
"genaiProviderSelected": "La detecció d'àudio està activada a la configuració, però actualment està desactivada per a aquesta càmera, de manera que la transcripció d'àudio no s'executarà. Torneu-lo a activar des de la vista en viu de la càmera, o comproveu si un perfil actiu l'està desactivant.",
|
||||
"audioDetectionRuntimeDisabled": "La detecció d'àudio està activada a la configuració, però actualment està desactivada per a aquesta càmera, de manera que la transcripció d'àudio no s'executarà. Torneu-lo a activar des de la vista en viu de la càmera, o comproveu si un perfil actiu l'està desactivant."
|
||||
"audioDetectionDisabled": "La detecció d'àudio no està activada per a aquesta càmera. La transcripció d'àudio requereix que la detecció d'àudio estigui activa."
|
||||
},
|
||||
"detect": {
|
||||
"fpsGreaterThanFive": "No es recomana establir el detect FPS superior a 5. Els valors més alts poden causar problemes de rendiment i no proporcionaran cap benefici.",
|
||||
@@ -1942,9 +1849,7 @@
|
||||
"maxFramesSet": "La configuració dels fotogrames màxims anul·la el comportament predeterminat i desactiva el seguiment d'objectes estacionaris. Hi ha molt poques situacions en què això sigui necessari, utilitzeu-lo amb precaució.",
|
||||
"squareResolution": "Una resolució de detecció quadrada és inusual. L'amplada i l'alçada de la detecció han de coincidir amb la relació d'aspecte de la càmera (per exemple, 16:9), no amb les dimensions del model de detecció d'objectes. Una relació d'aspecte no coincident pot estirar la imatge i reduir la precisió de detecció.",
|
||||
"resolutionHigh": "Aquesta resolució de detecció és més alta del recomanat i pot causar un ús més elevat dels recursos sense millorar la precisió de detecció. Es recomana una resolució de detecció a o per sota de 1080p per a la majoria de les càmeres.",
|
||||
"globalResolutionMultipleCameras": "S'estableix una resolució de detecció global mentre es configuren diverses càmeres. Tret que totes les càmeres comparteixin la mateixa resolució i relació d'aspecte, l'amplada i l'alçada de la detecció s'haurien de definir per càmera perquè coincideixi amb la relació d'aspecte nativa de cada càmera.",
|
||||
"sceneWithoutModel": "No s'ha configurat cap model de detecció per a aquesta escena, de manera que aquesta càmera torna al model amb una escena de 'Totes les càmeres'. Afegiu un model per a aquesta escena per donar la càmera pròpia.",
|
||||
"runtimeDisabled": "La detecció d'objectes està activada a la configuració, però actualment està desactivada per a aquesta càmera. Instantànies, articles de revisió i enriquiments com el reconeixement de rostres, el reconeixement de matrícules i la IA Generativa no funcionaran fins que no s'encengui des de la vista en viu de la càmera, o fins que el perfil actiu deixi d'inhabilitar-lo."
|
||||
"globalResolutionMultipleCameras": "S'estableix una resolució de detecció global mentre es configuren diverses càmeres. Tret que totes les càmeres comparteixin la mateixa resolució i relació d'aspecte, l'amplada i l'alçada de la detecció s'haurien de definir per càmera perquè coincideixi amb la relació d'aspecte nativa de cada càmera."
|
||||
},
|
||||
"faceRecognition": {
|
||||
"globalDisabled": "L'enriquiment del reconeixement facial s'ha d'habilitar perquè les funcions de reconeixement facial funcionin en aquesta càmera.",
|
||||
@@ -1957,12 +1862,10 @@
|
||||
"modelSizeLarge": "El model 'gran' està optimitzat per a matrícules multilínies. El model 'petit' proporciona un millor rendiment sobre 'gran' i s'ha d'utilitzar tret que la vostra regió utilitzi formats de placa multilínia."
|
||||
},
|
||||
"record": {
|
||||
"noRecordRole": "Cap flux té el rol de registre definit. L'enregistrament no funcionarà.",
|
||||
"noRecordSubRole": "Cap flux té definit el rol recordsubsub. L'enregistrament del substream no funcionarà."
|
||||
"noRecordRole": "Cap flux té el rol de registre definit. L'enregistrament no funcionarà."
|
||||
},
|
||||
"snapshots": {
|
||||
"detectDisabled": "La detecció d'objectes està desactivada. Les instantànies es generen a partir d'objectes rastrejats i no es crearan.",
|
||||
"detectRuntimeDisabled": "La detecció d'objectes està activada a la configuració, però actualment està desactivada per a aquesta càmera, de manera que no es crearan instantànies. Torneu-lo a activar des de la vista en viu de la càmera, o comproveu si un perfil actiu l'està desactivant."
|
||||
"detectDisabled": "La detecció d'objectes està desactivada. Les instantànies es generen a partir d'objectes rastrejats i no es crearan."
|
||||
},
|
||||
"objects": {
|
||||
"genaiNoDescriptionsProvider": "Heu de configurar un proveïdor de GenAI amb el rol 'descripcions' per a les descripcions que es generaran."
|
||||
@@ -1980,10 +1883,6 @@
|
||||
"model": {
|
||||
"optimizedFor320": "Frigate està optimitzada per a un model 320x320, que és la millor opció per a la majoria de configuracions. Un model 640x640 és més lent i només ajuda en escenaris específics.",
|
||||
"inputDimensionsNotDetectResolution": "L'amplada i l'alçada del model d'entrada són les dimensions d'entrada del model de detecció d'objectes, no la resolució de detecció de la càmera. Haurien de coincidir amb les dimensions del model que esteu utilitzant - típicament una mida quadrada com 320x320 o 640x640."
|
||||
},
|
||||
"birdseye": {
|
||||
"objectTrackingDetectDisabled": "Birdseye inclou objectes rastrejats, però la detecció d'objectes està desactivada per a aquesta càmera. La càmera no apareixerà a Birdseye.",
|
||||
"objectTrackingDetectRuntimeDisabled": "La detecció d'objectes està activada a la configuració, però actualment està desactivada per a aquesta càmera. Instantànies, articles de revisió i enriquiments com el reconeixement de rostres, el reconeixement de matrícules i la IA Generativa no funcionaran fins que no s'encengui des de la vista en viu de la càmera, o fins que el perfil actiu deixi d'inhabilitar-lo."
|
||||
}
|
||||
},
|
||||
"modelSize": {
|
||||
@@ -2014,10 +1913,6 @@
|
||||
"imageSource": {
|
||||
"recordings": "Gravacions",
|
||||
"previews": "Previsualitzacions"
|
||||
},
|
||||
"frameMode": {
|
||||
"frames": "Fotogrames",
|
||||
"annotated_frames": "Fotogrames anotats"
|
||||
}
|
||||
},
|
||||
"logger": {
|
||||
@@ -2045,46 +1940,5 @@
|
||||
"overrideGlobal": "Aquesta secció substitueix la configuració global",
|
||||
"overrideProfile": "Aquesta secció està substituïda pel perfil {{profile}}",
|
||||
"unsaved": "Aquesta secció té canvis sense desar"
|
||||
},
|
||||
"detectionModels": {
|
||||
"title": "Models de detecció",
|
||||
"description": "Configura els models de detecció d'objectes i el maquinari que s'executa. Les càmeres trien un model segons la seva escena a la configuració de detecció de la càmera.",
|
||||
"addModel": "Afegeix un model",
|
||||
"cameras_one": "{{count}} càmera",
|
||||
"cameras_many": "{{count}} càmeres",
|
||||
"cameras_other": "{{count}} càmeres",
|
||||
"scene": {
|
||||
"label": "Escena",
|
||||
"description": "L'entorn per al qual serveix aquest model. Les càmeres trien un model establint la mateixa escena a la seva configuració de detecció, i el model amb una escena de tots és utilitzat per qualsevol càmera que no en estableixi una."
|
||||
},
|
||||
"scenes": {
|
||||
"all": "Totes les càmeres",
|
||||
"indoor": "Interior",
|
||||
"outdoor": "Exterior",
|
||||
"indoor_thermal": "Tèrmiques interiors",
|
||||
"outdoor_thermal": "Tèrmiques exterior"
|
||||
},
|
||||
"hardware": {
|
||||
"label": "Maquinari",
|
||||
"placeholder": "Selecciona el maquinari",
|
||||
"loading": "S'està cercant el maquinari de detecció...",
|
||||
"none": "Cap maquinari seleccionat",
|
||||
"claimedBy": "utilitzat per {{scene}}",
|
||||
"detectorCount": "Detectors",
|
||||
"countRecommended_one": "Recomanat per a la càmera {{count}}",
|
||||
"countRecommended_many": "Recomanat per {{count}} càmeres",
|
||||
"countRecommended_other": "Recomanat per {{count}} càmeres",
|
||||
"unrecognized": "Aquest model està configurat per al maquinari que no s'ha trobat en aquest sistema: {{devices}}",
|
||||
"description": "El maquinari en el qual aquest model executa la seva detecció.",
|
||||
"detectorCountDescription": "Quants processos de detecció s'han d'executar en aquest maquinari. Més detectors es mantenen al dia amb més càmeres, a costa de la memòria extra del dispositiu.",
|
||||
"unitsDescription": "Cada unitat executa el seu propi procés de detecció. No es pot seleccionar una unitat ja utilitzada per un altre model."
|
||||
},
|
||||
"tabs": {
|
||||
"plus": "Frigate+",
|
||||
"custom": "Model personalitzat"
|
||||
},
|
||||
"plusModel": {
|
||||
"noModelSelected": "Selecciona un model Frigate+"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,8 +9,7 @@
|
||||
"nginx": "Registres de Nginix - Frigate",
|
||||
"websocket": "Registres de missatges - Frigate"
|
||||
},
|
||||
"enrichments": "Estadístiques complementàries - Frigate",
|
||||
"health": "Salut - Frigate"
|
||||
"enrichments": "Estadístiques complementàries - Frigate"
|
||||
},
|
||||
"title": "Sistema",
|
||||
"metrics": "Mètriques del sistema",
|
||||
@@ -140,11 +139,7 @@
|
||||
"title": "Sense utilitzar",
|
||||
"tips": "Aquest valor pot no de forma exacta representar l'espai lliure disponible a Frigate si tens altres fitxers emmagatzemats en la vostra unitat més enllà dels registres de Frigate. Frigate no rastreja l'ús d'emmagatzematge extern als seus registres."
|
||||
},
|
||||
"percentageOfTotalUsed": "Percentatge del total",
|
||||
"subStream": {
|
||||
"information": "Informació de l'emmagatzematge del subflux",
|
||||
"tips": "Les càmeres que enregistren un subflux mostren el seu ús original i de baixa qualitat per separat, utilitzant els mateixos noms que les opcions de qualitat en la reproducció de l'enregistrament. Els enregistraments de baixa qualitat es mantenen en disc fins que el seu període de retenció expira, de manera que aquesta avaria encara pot aparèixer per a una càmera després que s'hagi desactivat l'enregistrament de substream."
|
||||
}
|
||||
"percentageOfTotalUsed": "Percentatge del total"
|
||||
},
|
||||
"overview": "Visió general",
|
||||
"shm": {
|
||||
@@ -202,11 +197,7 @@
|
||||
"segmentLength": "Longitud del segment d'enregistrament:",
|
||||
"ok": "Fotogrames clau cada ,{{seconds}}s, bons per enregistrar i reproduir.",
|
||||
"unknown": "No s'ha pogut determinar l'espaiat dels fotogrames clau.",
|
||||
"recordDisabled": "L'enregistrament està desactivat per a aquesta càmera.",
|
||||
"warningFixed": "Els fotogrames clau estan uniformement espaiats però dispersos (cada ).{{seconds}}s). L'enregistrament encara funciona, però la reproducció en directe i la recerca comencen més lentament. Estableix l'interval I-frame (keyframe) de la càmera perquè coincideixi amb la seva velocitat de fotogrames.",
|
||||
"warningVariable": "L'espaiat dels fotogrames clau és inconsistent ({{minSeconds}}s a {{maxSeconds}}s), el qual normalment significa que un còdec intel·ligent (H.264+/H.265+) està habilitat. Això no és recomanable.",
|
||||
"errorFixed": "Els fotogrames clau cada the{{seconds}}s és més llarg que la longitud del segment d'enregistrament ({{segmentTime}}s), de manera que alguns segments no tenen fotogrames clau i no es reproduiran. Escurça l'interval I-frame (keyframe) de la càmera perquè coincideixi amb la seva velocitat de fotogrames.",
|
||||
"errorVariable": "Els buits dels fotogrames clau arriben a the{{seconds}}s, més llargs que la longitud del segment d'enregistrament ({{segmentTime}}s). Alguns segments no tindran un fotograma clau, el qual trenca la reproducció. Desactiva el còdec intel·ligent/+ a la càmera o escurça el seu interval de fotogrames clau."
|
||||
"recordDisabled": "L'enregistrament està desactivat per a aquesta càmera."
|
||||
}
|
||||
},
|
||||
"title": "Càmeres",
|
||||
@@ -243,11 +234,7 @@
|
||||
"detectHighCpuUsage": "{{camera}} te un ús elevat de CPU per la detecció ({{detectAvg}}%)",
|
||||
"detectIsVerySlow": "{{detect}} és molt lent ({{speed}} ms)",
|
||||
"detectIsSlow": "{{detect}} és lent ({{speed}} ms)",
|
||||
"debugReplayActive": "La sessió de repetició de depuració està activa",
|
||||
"cameraSkippedDetections": "{{camera}} està ometent la detecció en {{pct}}% de fotogrames",
|
||||
"systemNotices_one": "{{count}} avís del sistema",
|
||||
"systemNotices_other": "{{count}} avisos del sistema",
|
||||
"retentionUnmet": "Els enregistraments s'estan suprimint abans que acabi el seu període de retenció a l'espai lliure"
|
||||
"debugReplayActive": "La sessió de repetició de depuració està activa"
|
||||
},
|
||||
"enrichments": {
|
||||
"title": "Anàlisi avançada",
|
||||
@@ -275,93 +262,5 @@
|
||||
},
|
||||
"infPerSecond": "Inferències per segon",
|
||||
"averageInf": "Temps mitjà d'inferència"
|
||||
},
|
||||
"health": {
|
||||
"title": "Salut",
|
||||
"notices": {
|
||||
"title": "Avís",
|
||||
"empty": "La instal·lació de Frigate és saludable",
|
||||
"dismiss": "Descarta",
|
||||
"openSettings": "Obre la configuració",
|
||||
"openLink": "Obre l'enllaç",
|
||||
"noMatches": "No hi ha avisos que coincideixin amb el filtre",
|
||||
"dismissedTitle": "Descartat",
|
||||
"noneDismissed": "No hi ha avisos descartats",
|
||||
"clearDismissed": "Neteja descartada",
|
||||
"clearDismissedTitle": "Voleu netejar els avisos descartats?",
|
||||
"clearDismissedDesc": "S'elimina cada avís acomiadat. Les comprovacions de configuració i flux es mostren de nou immediatament, i altres avisos tornen la propera vegada que succeeixin.",
|
||||
"firstSeen_one": "{{time}} vist per primera vegada",
|
||||
"firstSeen_other": "{{time}} · {{count}} vegades",
|
||||
"dismissedAt": "S'ha suprimit {{time}}",
|
||||
"filter": {
|
||||
"showDismissed": "Mostra descartat",
|
||||
"severity": "Severitat",
|
||||
"warning": "Avís",
|
||||
"error": "Error",
|
||||
"info": "Info"
|
||||
},
|
||||
"kinds": {
|
||||
"detector_stuck": "S'ha reiniciat el detector {{detector}} després que deixés de respondre",
|
||||
"model_download_failed": "Ha fallat la baixada de {{file}} per {{model}}: {{error}}",
|
||||
"skipped_detections": "La detecció no ha pogut mantenir el {{pct}}% de fotogrames durant més d'un minut",
|
||||
"shm_too_low": "L'assignació /dev/shm ({{total}} MB) s'hauria d'augmentar a com a mínim {{min}} MB",
|
||||
"failed_login_one": "Error en l'intent d'inici de sessió de {{user}}",
|
||||
"failed_login_other": "Intents d'inici de sessió fallits per {{user}}",
|
||||
"update_available": "Frigate {{version}} està disponible"
|
||||
},
|
||||
"streamPrefix": "Flux {{index}}: {{message}}",
|
||||
"streamPrefixRestream": "Flux {{index}} (via go2rtc): {{message}}",
|
||||
"streamProbeFailed": "No s'ha pogut provar el flux {{index}}: {{error}}",
|
||||
"cameraProbeFailed": "No s'han pogut explorar els fluxos: {{error}}"
|
||||
},
|
||||
"hardware": {
|
||||
"title": "Maquinari",
|
||||
"objectDetection": "Detecció d'objectes",
|
||||
"hardwareAcceleration": "Acceleració del maquinari",
|
||||
"enrichments": {
|
||||
"title": "Enriquiments",
|
||||
"semantic_search": "Cerca semàntica",
|
||||
"face_recognition": "Reconeixement facial",
|
||||
"lpr": "Reconeixement de matricules",
|
||||
"audio_transcription": "Transcripció d'àudio"
|
||||
},
|
||||
"cameraConnections": "Connexions de la càmera",
|
||||
"allCamerasExcellent": "Totes les càmeres tenen una excel·lent connexió.",
|
||||
"fps": "{{camera}} / {{expected}} fps",
|
||||
"nothingConfigured": "Res configurat",
|
||||
"allCameras": "Totes les càmeres",
|
||||
"probeUnavailable": "La detecció de maquinari no està disponible",
|
||||
"justStarted": "Frigate acaba de començar",
|
||||
"deviceNotFound": "{{devices}} no s'ha trobat en aquest sistema",
|
||||
"detectorNotRunning": "El procés del detector no s'està executant",
|
||||
"inferenceVerySlow": "La inferència és molt lenta ({{speed}} ms)",
|
||||
"inferenceSlow": "La inferència és lenta ({{speed}} ms)",
|
||||
"customArgs": "Arguments personalitzats del ffmpeg",
|
||||
"customArgsNotVerified": "Arguments personalitzats del ffmpeg, no verificats",
|
||||
"hwaccelNotConfigured": "No s'utilitza cap descodificació de maquinari, però {{family}} està disponible. Seleccioneu-lo a la configuració del ffmpeg",
|
||||
"hwaccelHardwareMissing": "{{family}} està configurat, però la sonda de maquinari no ho ha informat",
|
||||
"unrecognizedDevice": "Sobreescriu el dispositiu no reconegut, no verificat",
|
||||
"decoderUsage": "descodificador {{usage}}",
|
||||
"remoteProvider": "Proveïdor remot",
|
||||
"acceleratorMissing": "Configurat per {{device}} però no s'ha trobat cap accelerador compatible",
|
||||
"modelNotRunYet": "El model encara no s'ha executat, el dispositiu es verifica després del primer ús",
|
||||
"fellBackToCpu": "Configurat per {{device}} però executant-se a la CPU",
|
||||
"cpuDespiteAccelerator": "S'està executant a la CPU encara que hi ha disponible un accelerador",
|
||||
"probed": "Profund",
|
||||
"probing": "S'està sondejant...",
|
||||
"recheck": "Torna a comprovar el maquinari",
|
||||
"cameraStreams": "Fluxos de la càmera",
|
||||
"streamsNotChecked": "Encara no s'ha comprovat",
|
||||
"streamsChecking": "S'està comprovant {{done}} de {{total}}",
|
||||
"streamsClean": "No hi ha problemes de flux",
|
||||
"checked": "Comprovat",
|
||||
"runAgain": "Torna a executar",
|
||||
"runStreamChecks": "Executa les comprovacions de flux",
|
||||
"streamsChecked_one": "S'ha comprovat la càmera {{count}}",
|
||||
"streamsChecked_other": "{{count}} càmeres comprovades",
|
||||
"streamsFlagged_one": "{{count}} amb problemes, llistat a Avisos",
|
||||
"streamsFlagged_other": "{{count}} amb problemes, llistat a Avisos",
|
||||
"inferenceMs": "{{speed}} ms"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
"title": "Šířka pásma:",
|
||||
"short": "Šířka pásma"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latence:",
|
||||
"value": "{{seconds}} sekund",
|
||||
"short": {
|
||||
"title": "Latence",
|
||||
"value": "{{seconds}} sek"
|
||||
}
|
||||
},
|
||||
"totalFrames": "Celkový počet snímků:",
|
||||
"droppedFrames": {
|
||||
"title": "Ztracené snímky:",
|
||||
|
||||
@@ -343,8 +343,5 @@
|
||||
"engine": "Motor",
|
||||
"light_engine": "Lille motor",
|
||||
"swing_music": "Swing musik",
|
||||
"bluegrass": "Bluegrass",
|
||||
"folk_music": "Folkemusik",
|
||||
"echo": "Ekko",
|
||||
"pulse": "Puls"
|
||||
"bluegrass": "Bluegrass"
|
||||
}
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
"title": "Båndbredde:",
|
||||
"short": "Båndbredde"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latenstid:",
|
||||
"value": "{{seconds}} sekunder",
|
||||
"short": {
|
||||
"title": "Latenstid",
|
||||
"value": "{{seconds}} sek"
|
||||
}
|
||||
},
|
||||
"droppedFrames": {
|
||||
"short": {
|
||||
"title": "Tabt",
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
"title": "Bandbreite:",
|
||||
"short": "Bandbreite"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latenz:",
|
||||
"value": "{{seconds}} Sekunden",
|
||||
"short": {
|
||||
"title": "Latenz",
|
||||
"value": "{{seconds}} s"
|
||||
}
|
||||
},
|
||||
"droppedFrames": {
|
||||
"short": {
|
||||
"title": "Ausgelassen",
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
"title": "Ταχύτητα:",
|
||||
"short": "Ταχύτητα"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Καθυστέρηση:",
|
||||
"value": "{{seconds}} δευτερόλεπτα",
|
||||
"short": {
|
||||
"title": "Καθυστέρηση",
|
||||
"value": "{{seconds}} δευτερόλεπτα"
|
||||
}
|
||||
},
|
||||
"totalFrames": "Συνολικός αριθμός Καρέ:",
|
||||
"droppedFrames": {
|
||||
"title": "Απορριφθέντα καρέ:",
|
||||
|
||||
@@ -1208,8 +1208,9 @@
|
||||
"desc": "Frigate can natively send push notifications to your device when it is running in the browser or installed as a PWA."
|
||||
},
|
||||
"notificationUnavailable": {
|
||||
"desc": "Web push notifications require a secure context (https://…). This is a browser limitation. Access Frigate securely to use notifications.",
|
||||
"descPwa": "On iOS, web push notifications are only available when Frigate is installed to your Home Screen. Open the Share menu, choose Add to Home Screen, then open Frigate from the new icon to register this device for notifications."
|
||||
"title": "Notifications Unavailable",
|
||||
"desc": "Web push notifications require a secure context (<code>https://…</code>). This is a browser limitation. Access Frigate securely to use notifications.",
|
||||
"descPwa": "On iOS, web push notifications are only available when Frigate is installed to your Home Screen. Open the <strong>Share</strong> menu, choose <strong>Add to Home Screen</strong>, then open Frigate from the new icon to register this device for notifications."
|
||||
},
|
||||
"globalSettings": {
|
||||
"title": "Global Settings",
|
||||
@@ -1315,6 +1316,7 @@
|
||||
"triggers": {
|
||||
"documentTitle": "Triggers",
|
||||
"semanticSearch": {
|
||||
"title": "Semantic Search is disabled",
|
||||
"desc": "Semantic Search must be enabled to use Triggers."
|
||||
},
|
||||
"management": {
|
||||
|
||||
@@ -95,7 +95,7 @@
|
||||
"setPassword": "Establecer contraseña",
|
||||
"current": "Usuario actual: {{user}}"
|
||||
},
|
||||
"systemMetrics": "Salud y Métricas del sistema",
|
||||
"systemMetrics": "Métricas del sistema",
|
||||
"help": "Ayuda",
|
||||
"system": "Sistema",
|
||||
"configuration": "Configuración",
|
||||
@@ -147,8 +147,7 @@
|
||||
"ur": "اردو (Urdu)",
|
||||
"hr": "Hrvatski (Croata)",
|
||||
"bs": "Bosanski (Bosnio)",
|
||||
"zhHant": "繁體中文 (Chino Tradicional)",
|
||||
"be": "Bielorruso"
|
||||
"zhHant": "繁體中文 (Chino Tradicional)"
|
||||
},
|
||||
"appearance": "Apariencia",
|
||||
"darkMode": {
|
||||
@@ -260,10 +259,7 @@
|
||||
"saveAll": "Guardar todo",
|
||||
"savingAll": "Guardando todo…",
|
||||
"undoAll": "Deshacer todo",
|
||||
"retry": "Reintentar",
|
||||
"expand": "Expandir",
|
||||
"collapse": "Colapsar",
|
||||
"reload": "Recargar"
|
||||
"retry": "Reintentar"
|
||||
},
|
||||
"toast": {
|
||||
"save": {
|
||||
@@ -331,36 +327,5 @@
|
||||
"validation_errors": "Errores de validación",
|
||||
"credentialField": {
|
||||
"savedPlaceholder": "Guardado — déjalo en blanco para mantener el actual"
|
||||
},
|
||||
"commandMenu": {
|
||||
"action": {
|
||||
"toggleTheme": "Cambiar de modo claro a modo oscuro"
|
||||
},
|
||||
"title": "Menú de Comandos",
|
||||
"description": "Buscar páginas, cámaras, configuraciones y acciones",
|
||||
"placeholder": "Buscar páginas, cámaras, configuraciones y acciones",
|
||||
"empty": "No se han encontrado coincidencias",
|
||||
"hint": "{{key}} o / para abrir, Enter para ejecutar",
|
||||
"section": {
|
||||
"recent": "Recientes",
|
||||
"pages": "Páginas",
|
||||
"cameras": "Cámaras",
|
||||
"cameraGroups": "Grupos de cámaras",
|
||||
"settings": "Configuración",
|
||||
"actions": "Acciones"
|
||||
},
|
||||
"camera": {
|
||||
"live": "En vivo",
|
||||
"review": "Revisión"
|
||||
}
|
||||
},
|
||||
"error": {
|
||||
"title": "Esta página ha dejado de funcionar",
|
||||
"desc": "Ha ocurrido un error inesperado en esta página. Recargarla generalmente resuelve el problema. Si sigue sucediendo, copia los detalles y adjuntalos en una nueva discusión en GitHub.",
|
||||
"staleTitle": "Recarga requerida",
|
||||
"staleDesc": "Una parte de esta interfaz no pudo ser cargada, lo que usualmente significa que Frigate fue actualizado mientras esta pestaña estaba abierta. Recarga la página para ver la nueva versión.",
|
||||
"partial": "Una parte de la interfaz ha dejado de funcionar.",
|
||||
"copyDetails": "Copiar detalles",
|
||||
"copyFailed": "Los detalles no pudieron ser copiados al portapapeles"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,14 @@
|
||||
"title": "Ancho de banda:",
|
||||
"short": "Ancho de banda"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latencia:",
|
||||
"short": {
|
||||
"title": "Latencia",
|
||||
"value": "{{seconds}} seg"
|
||||
},
|
||||
"value": "{{seconds}} segundos"
|
||||
},
|
||||
"totalFrames": "Fotogramas totales:",
|
||||
"droppedFrames": {
|
||||
"title": "Fotogramas perdidos:",
|
||||
|
||||
@@ -274,7 +274,7 @@
|
||||
"soundtrack_music": "Filmimuusika",
|
||||
"jingle": "Kõlisemine/tilisemine",
|
||||
"theme_music": "Tunnusmuusika",
|
||||
"steel_guitar": "Steel-kitarr",
|
||||
"steel_guitar": "Steel Kitarr",
|
||||
"tapping": "Koputamine",
|
||||
"strum": "Klimberdus",
|
||||
"drum_machine": "Trummimasin",
|
||||
@@ -337,13 +337,5 @@
|
||||
"television": "Televiisor",
|
||||
"scream": "Karjumine",
|
||||
"pour": "Valamine",
|
||||
"drip": "Tilkumine",
|
||||
"snare_drum": "Väike trumm / soolotrumm",
|
||||
"rimshot": "Trummi äärelöök",
|
||||
"drum_roll": "Trummipõrin",
|
||||
"timpani": "Timpanid",
|
||||
"tabla": "Tabla-trumm Indiast",
|
||||
"cymbal": "Simbel",
|
||||
"hi_hat": "Pedaaliga taldrikukomplekt",
|
||||
"wood_block": "Väike õõnesplokktrumm"
|
||||
"drip": "Tilkumine"
|
||||
}
|
||||
|
||||
@@ -146,9 +146,9 @@
|
||||
"be": "Беларуская (valgevene keel)"
|
||||
},
|
||||
"system": "Süsteem",
|
||||
"systemMetrics": "Süsteemi korrasolek ja meetrika",
|
||||
"systemMetrics": "Süsteemi meetrika",
|
||||
"configuration": "Seadistused",
|
||||
"systemLogs": "Logid",
|
||||
"systemLogs": "Süsteemi logid",
|
||||
"configurationEditor": "Seadistuste haldur",
|
||||
"languages": "Keeled",
|
||||
"appearance": "Välimus",
|
||||
@@ -253,10 +253,7 @@
|
||||
"savingAll": "Salvestan kõiki…",
|
||||
"undoAll": "Pööra kõik tegevused tagasi",
|
||||
"applying": "Võtan kasutusele…",
|
||||
"retry": "Proovi uuesti",
|
||||
"expand": "Laienda",
|
||||
"collapse": "Ahenda",
|
||||
"reload": "Laadi uuesti"
|
||||
"retry": "Proovi uuesti"
|
||||
},
|
||||
"label": {
|
||||
"back": "Mine tagasi",
|
||||
@@ -324,36 +321,5 @@
|
||||
"validation_errors": "Valideerimise vead",
|
||||
"credentialField": {
|
||||
"savedPlaceholder": "Salvestatud - senise kasutamiseks jäta tühjaks"
|
||||
},
|
||||
"error": {
|
||||
"title": "Leht lõpetas toimimise",
|
||||
"desc": "Lehel tekkis ootamatu viga. Tavaliselt aitab lehe uuesti laadimine seda kõrvaldada. Kui viga kordub, kopeeri üksikasjad ja lisa need GitHubi arutelusse või veakirjeldusse.",
|
||||
"staleTitle": "Uuesti laadimine on vajalik",
|
||||
"staleDesc": "Osa kasutajaliidesest ei õnnestunud laadida, mis tähendab tavaliselt, et Frigate'i sai uuendatud, kui see vahekaart oli avatud. Uue versiooni kuvamiseks laadi leht uuesti.",
|
||||
"partial": "Osa kasutajaliidestest lõpetas toimimise.",
|
||||
"copyDetails": "Kopeeri üksikasjad",
|
||||
"copyFailed": "Üksikasjade kopeerimine lõikelauale ei õnnestunud"
|
||||
},
|
||||
"commandMenu": {
|
||||
"title": "Käsumenüü",
|
||||
"description": "Otsi lehti, kaameraid, seadistusi ja tegevusi",
|
||||
"placeholder": "Otsi lehti, kaameraid, seadistusi ja tegevusi",
|
||||
"empty": "Vasteid ei leidu",
|
||||
"hint": "Vajuta avamiseks {{key}} või käivitamiseks sisestusklahvi",
|
||||
"section": {
|
||||
"recent": "Hiljutine",
|
||||
"pages": "Lehti",
|
||||
"cameras": "Kaamerad",
|
||||
"cameraGroups": "Kaameragrupid",
|
||||
"settings": "Seadistused",
|
||||
"actions": "Tegevused"
|
||||
},
|
||||
"camera": {
|
||||
"live": "Vaade reaalajas",
|
||||
"review": "Ülevaade"
|
||||
},
|
||||
"action": {
|
||||
"toggleTheme": "Lülita hele ja tume vaade sisse/välja"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,15 +143,6 @@
|
||||
"partial": "Alustasin {{successful}}/{{total}} ekspordiga. Ebaõnnestusid: {{failedItems}}",
|
||||
"failed": "{{total}} ekspordi algatamine ebaõnnestus. Ebaõnnestunud: {{failedItems}}"
|
||||
}
|
||||
},
|
||||
"stream": {
|
||||
"label": "Kvaliteet",
|
||||
"auto": "Automaatne",
|
||||
"main": "Algne",
|
||||
"sub": "Madal",
|
||||
"autoDesc": "Kasutab põhilist voogedastust ja lülitub madalama kvaliteediga alamvoogedastusele, kui põhiline pole kättesaadav.",
|
||||
"subDesc": "Eksporditakse ainult madalama kvaliteediga alamvoogedastus. Ajavahemikud, mil see pole kättesaadav, jäävad välja.",
|
||||
"mainDesc": "Eksporditakse ainult algse kvaliteediga põhiline voogedastus. Ajavahemikud, mil see pole kättesaadav, jäävad välja."
|
||||
}
|
||||
},
|
||||
"streaming": {
|
||||
@@ -173,8 +164,7 @@
|
||||
"export": "Ekspordi",
|
||||
"markAsReviewed": "Märgi ülevaadatuks",
|
||||
"markAsUnreviewed": "Märgi mitteülevaadatuks",
|
||||
"deleteNow": "Kustuta kohe",
|
||||
"generateDescription": "Koosta kirjeldus"
|
||||
"deleteNow": "Kustuta kohe"
|
||||
},
|
||||
"confirmDelete": {
|
||||
"title": "Kinnita kustutamine",
|
||||
@@ -193,12 +183,6 @@
|
||||
"custom": "Kohandatud ajatempel",
|
||||
"button": "Jaga ajatempliga linki",
|
||||
"shareTitle": "Frigate ülevaate ajatempel: {{camera}}"
|
||||
},
|
||||
"genaiDescription": {
|
||||
"toast": {
|
||||
"error": "Kirjelduse pärimine ei õnnestunud: {{error}}",
|
||||
"success": "Selle ülevaatamisele kuuluva objekti jaoks oled palunud „GenAI“ põhise kirjelduse koostamist."
|
||||
}
|
||||
}
|
||||
},
|
||||
"imagePicker": {
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
"title": "Ribalaius:",
|
||||
"short": "Ribalaius"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latentsus:",
|
||||
"value": "{{seconds}} sekundit",
|
||||
"short": {
|
||||
"title": "Latentsus",
|
||||
"value": "{{seconds}} sek"
|
||||
}
|
||||
},
|
||||
"totalFrames": "Kaadreid kokku:",
|
||||
"droppedFrames": {
|
||||
"title": "Vahelejäänud kaadreid:",
|
||||
@@ -37,23 +45,8 @@
|
||||
"submittedFrigatePlus": "Kaadri saatmine Frigate+ teenusesse õnnestus"
|
||||
},
|
||||
"error": {
|
||||
"submitFrigatePlusFailed": "Kaadri saatmine Frigate+ teenusesse ei õnnestunud",
|
||||
"playRecordingsFailed": "Salvestiste esitamine ei õnnestunud (viga {{code}}): {{message}}"
|
||||
"submitFrigatePlusFailed": "Kaadri saatmine Frigate+ teenusesse ei õnnestunud"
|
||||
}
|
||||
},
|
||||
"cameraOff": "Kaamera on lülitatud välja",
|
||||
"quality": {
|
||||
"auto": "Automaatne",
|
||||
"autoLow": "Esita madala kvaliteediga (väiksem ribalaius)",
|
||||
"autoLowCodec": "Esitamisel madala kvaliteediga (see brauser ei toeta algset vormingut)",
|
||||
"autoLowSaveData": "Esitamisel madala kvaliteediga (säästab andmeruumi)",
|
||||
"main": "Algne kvaliteet",
|
||||
"sub": "Madal kvaliteet",
|
||||
"notSupportedBrowser": "Pole selles brauseris toetatud",
|
||||
"label": "Kvaliteet",
|
||||
"noAudio": "Ilma heliribata",
|
||||
"audioRate": "{{rate}} kHz heliriba",
|
||||
"audioCodecRate": "{{codec}} {{rate}} kHz",
|
||||
"noRecordings": "Sellest ajavahemikust pole salvestisi"
|
||||
}
|
||||
"cameraOff": "Kaamera on lülitatud välja"
|
||||
}
|
||||
|
||||
@@ -44,15 +44,7 @@
|
||||
},
|
||||
"alerts": {
|
||||
"enabled": {
|
||||
"label": "Luba häired",
|
||||
"description": "Luba häirete loomine selle kaamera jaoks."
|
||||
},
|
||||
"labels": {
|
||||
"label": "Häirete sildid",
|
||||
"description": "Objektide sildid, mille alusel häiret luua (nt: auto, isik)."
|
||||
},
|
||||
"required_zones": {
|
||||
"label": "Nõutavad tsoonid"
|
||||
"label": "Luba häired"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -115,13 +115,6 @@
|
||||
"enabled": {
|
||||
"label": "Luba häired",
|
||||
"description": "Luba või keela kõigi kaamerate häirete genereerimine; seda saab kaamerati eraldi muuta."
|
||||
},
|
||||
"labels": {
|
||||
"label": "Häirete sildid",
|
||||
"description": "Objektide sildid, mille alusel häiret luua (nt: auto, isik)."
|
||||
},
|
||||
"required_zones": {
|
||||
"label": "Nõutavad tsoonid"
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -136,7 +129,7 @@
|
||||
},
|
||||
"language": {
|
||||
"label": "Üleskirjutuse keel",
|
||||
"description": "Üleskirjutuse/tõlkimise jaoks kasutatav keelekood (näiteks „en“ inglise keele puhul) või „auto“, kui tahad et keelemudel tuvastaks selle automaatselt. Toetatud keelekoodid leiad lehelt https://whisper-api.com/docs/languages/."
|
||||
"description": "Üleskirjutuse/tõlkimise jaoks kasutatav keelekood (näiteks „en” inglise keele puhul). Toetatud keelekoodid leiad lehelt https://whisper-api.com/docs/languages/."
|
||||
},
|
||||
"device": {
|
||||
"label": "Üleskirjutusseade"
|
||||
|
||||
@@ -31,8 +31,5 @@
|
||||
},
|
||||
"detect": {
|
||||
"dimensionMustBeEven": "Peab olema paarisarv."
|
||||
},
|
||||
"models": {
|
||||
"defaultRequired": "Üks mudel peab kasutama stseeni „Kõik kaamerad“. Ilma selleta ei ole ühelgi kaameral, millel stseen on valimata,pole tagavaravariandina kasutatavat mudelit."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,12 +26,6 @@
|
||||
"auto_scroll": {
|
||||
"title": "Automaatne kerimine",
|
||||
"desc": "Jälgi uusi sõnumeid kohe, kui need saabuvad."
|
||||
},
|
||||
"always_allow": {
|
||||
"title": "Alati lubatud tegevused",
|
||||
"desc": "Tegevused, mida Abiline võib käivitada ilma eelnevalt luba küsimata.",
|
||||
"none": "Määramata",
|
||||
"reset": "Lähtesta"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
@@ -74,15 +68,5 @@
|
||||
},
|
||||
"thinking": {
|
||||
"toggle": "Näita mõtlemise olekut või peida see"
|
||||
},
|
||||
"approval": {
|
||||
"title": "Kas lubad „{{tool}}“ tarviku kasutamist?",
|
||||
"desc": "Selle tegevusega muudad Frigate'is midagi. Enne kinnitamist vaata üksikasjad üle.",
|
||||
"approve": "Kiida heaks",
|
||||
"always_allow": "Luba alati",
|
||||
"reject": "Lükka tagasi",
|
||||
"approved": "Heakskiidetud",
|
||||
"rejected": "Tagasilükatud",
|
||||
"placeholder": "Jätkamaks kiida ootel tegevus heaks või lükka ta tagasi"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,6 +46,5 @@
|
||||
},
|
||||
"train": {
|
||||
"titleShort": "Hiljutised"
|
||||
},
|
||||
"disabled": "Keelatud"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,5 @@
|
||||
"crop": "Kadreeri filtreerimiseks",
|
||||
"cropAria": "Lülita filtreeritud alade kadreeritud eelvaated sisse/välja",
|
||||
"cropDesc": "Täiskaadri kuvamise asemel suumi eelvaated valitud filtritega märgitud alani."
|
||||
},
|
||||
"subOnlyQuality": "Sellest ajavahemikust on saadaval vaid madala kvaliteediga salvestised"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -56,7 +56,7 @@
|
||||
"streamTitle": "Voog {{number}}",
|
||||
"streamUrl": "Voo URL",
|
||||
"addStream": "Lisa voog",
|
||||
"description": "Seadista omadusi, voogedastusrolle ja lisa oma kaamerale täiendavaid vooge.",
|
||||
"description": "Seadista voogedastusrolle ja lisa oma kaamerale täiendavaid vooge.",
|
||||
"streamsTitle": "Kaamera vood"
|
||||
},
|
||||
"steps": {
|
||||
@@ -447,7 +447,7 @@
|
||||
"systemTelemetry": "Telemeetria",
|
||||
"systemBirdseye": "Vaade linnulennult",
|
||||
"systemFfmpeg": "FFmpeg",
|
||||
"systemDetectorsAndModel": "Tuvastusmudelid",
|
||||
"systemDetectorsAndModel": "Tuvastamine ja mudelid",
|
||||
"systemMqtt": "MQTT",
|
||||
"systemGo2rtcStreams": "go2rtc voogedastus",
|
||||
"integrationSemanticSearch": "Semantiline otsing",
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
"title": "پهنای باند:",
|
||||
"short": "پهنای باند"
|
||||
},
|
||||
"latency": {
|
||||
"title": "تأخیر:",
|
||||
"value": "{{seconds}} ثانیهها",
|
||||
"short": {
|
||||
"title": "تأخیر",
|
||||
"value": "{{seconds}} ثانیه"
|
||||
}
|
||||
},
|
||||
"totalFrames": "مجموع فریمها:",
|
||||
"droppedFrames": {
|
||||
"title": "فریمهای از دسترفته:",
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
"title": "Kaistanleveys:",
|
||||
"short": "Kaistanleveys"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latenssi:",
|
||||
"value": "{{seconds}} sekuntia",
|
||||
"short": {
|
||||
"value": "{{seconds}} sek",
|
||||
"title": "Latenssi"
|
||||
}
|
||||
},
|
||||
"totalFrames": "Kehyksiä yhteensä:",
|
||||
"droppedFrames": {
|
||||
"title": "Pudotettuja kehyksiä:",
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
"title": "Bande passante :",
|
||||
"short": "Bande passante"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latence :",
|
||||
"value": "{{seconds}} secondes",
|
||||
"short": {
|
||||
"title": "Latence",
|
||||
"value": "{{seconds}} s"
|
||||
}
|
||||
},
|
||||
"droppedFrames": {
|
||||
"short": {
|
||||
"value": "{{droppedFrames}} images",
|
||||
|
||||
@@ -16,6 +16,14 @@
|
||||
"title": "רוחב-פס:",
|
||||
"short": "רוחב-פס"
|
||||
},
|
||||
"latency": {
|
||||
"title": "השהיה:",
|
||||
"value": "{{seconds}} שניות",
|
||||
"short": {
|
||||
"title": "השהיה",
|
||||
"value": "{{seconds}} שניה"
|
||||
}
|
||||
},
|
||||
"decodedFrames": "פריימים מפוענחים:",
|
||||
"droppedFrameRate": "קצב פריימים מופחת:",
|
||||
"totalFrames": "סך כל המסגרות:"
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
"short": "Vrsta",
|
||||
"title": "Tip Streama:"
|
||||
},
|
||||
"latency": {
|
||||
"value": "{{seconds}} sekundi",
|
||||
"short": {
|
||||
"value": "{{seconds}} sekundi",
|
||||
"title": "Kašnjenje"
|
||||
},
|
||||
"title": "Kašnjenje:"
|
||||
},
|
||||
"bandwidth": {
|
||||
"title": "Mrežna propusnost:",
|
||||
"short": "Mrežna propusnost"
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
"title": "Sávszélesség:",
|
||||
"short": "Sávszélesség"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Késleltetés:",
|
||||
"value": "{{seconds}} másodperc",
|
||||
"short": {
|
||||
"title": "Késleltetés",
|
||||
"value": "{{seconds}} másodperc"
|
||||
}
|
||||
},
|
||||
"droppedFrames": {
|
||||
"title": "Hibás Képek:",
|
||||
"short": {
|
||||
|
||||
@@ -76,9 +76,9 @@
|
||||
"menu": {
|
||||
"system": "Sistem",
|
||||
"profiles": "Profil",
|
||||
"systemMetrics": "Metrik sistemKesehatan dan Metrik",
|
||||
"systemMetrics": "Metrik sistem",
|
||||
"configuration": "Konfigurasi",
|
||||
"systemLogs": "Log",
|
||||
"systemLogs": "Log sistem",
|
||||
"settings": "Pengaturan",
|
||||
"configurationEditor": "Editor Konfigurasi",
|
||||
"languages": "Bahasa",
|
||||
@@ -127,8 +127,7 @@
|
||||
"withSystem": {
|
||||
"label": "Gunakan pengaturan sistem untuk bahasa"
|
||||
},
|
||||
"zhHant": "繁體中文 (Tionghoa Tradisional)",
|
||||
"be": "Bahasa Belarusia"
|
||||
"zhHant": "繁體中文 (Tionghoa Tradisional)"
|
||||
},
|
||||
"appearance": "Tampilan",
|
||||
"darkMode": {
|
||||
@@ -265,10 +264,7 @@
|
||||
"saveAll": "Simpan Semua",
|
||||
"savingAll": "Menyimpan Semua…",
|
||||
"undoAll": "Urungkan Semua",
|
||||
"retry": "Coba Lagi",
|
||||
"expand": "Perluas",
|
||||
"collapse": "Ciutkan",
|
||||
"reload": "Muat ulang"
|
||||
"retry": "Coba Lagi"
|
||||
},
|
||||
"toast": {
|
||||
"copyUrlToClipboard": "URL disalin ke papan klip.",
|
||||
@@ -317,36 +313,5 @@
|
||||
"validation_errors": "Kesalahan Validasi",
|
||||
"credentialField": {
|
||||
"savedPlaceholder": "Tersimpan — biarkan kosong untuk mempertahankan yang saat ini"
|
||||
},
|
||||
"error": {
|
||||
"title": "Halaman ini berhenti bekerja",
|
||||
"desc": "Halaman mengalami kesalahan yang tidak terduga. Memuat ulang biasanya akan mengatasinya. Jika masih terus terjadi, salin detailnya dan lampirkan ke diskusi di GitHub.",
|
||||
"staleTitle": "Muat ulang diperlukan",
|
||||
"staleDesc": "Sebagian antarmuka tidak dapat dimuat, yang biasanya berarti Frigate telah diperbarui saat tab ini terbuka. Muat ulang untuk mengambil versi baru.",
|
||||
"partial": "Sebagian antarmuka berhenti bekerja.",
|
||||
"copyDetails": "Salin detail",
|
||||
"copyFailed": "Gagal menyalin detail ke papan klip"
|
||||
},
|
||||
"commandMenu": {
|
||||
"title": "Menu perintah",
|
||||
"description": "Cari halaman, kamera, pengaturan, dan tindakan",
|
||||
"placeholder": "Cari halaman, kamera, pengaturan, dan tindakan",
|
||||
"empty": "Tidak ada kecocokan",
|
||||
"hint": "{{key}} atau / untuk membuka, Enter untuk menjalankan",
|
||||
"section": {
|
||||
"recent": "Terkini",
|
||||
"pages": "Halaman",
|
||||
"cameras": "Kamera",
|
||||
"cameraGroups": "Grup kamera",
|
||||
"settings": "Pengaturan",
|
||||
"actions": "Tindakan"
|
||||
},
|
||||
"camera": {
|
||||
"live": "Langsung",
|
||||
"review": "Tinjauan"
|
||||
},
|
||||
"action": {
|
||||
"toggleTheme": "Beralih antara mode terang dan gelap"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,9 +65,8 @@
|
||||
"batchQueuedSuccess_other": "{{count}} ekspor antrian.",
|
||||
"batchQueueFailed": "Gagal mengantrekan {{total}} ekspor. Kamera yang gagal: {{failedCameras}}",
|
||||
"error": {
|
||||
"failed": "Gagal mengantrekan ekspor: {{error}}",
|
||||
"noValidTimeSelected": "Rentang waktu yang dipilih tidak valid",
|
||||
"endTimeMustAfterStartTime": "Waktu selesai harus setelah waktu mulai"
|
||||
"failed": "Ekspor gagal mengantri: {{error}}",
|
||||
"noValidTimeSelected": "Rentang waktu yang dipilih tidak valid"
|
||||
}
|
||||
},
|
||||
"case": {
|
||||
@@ -121,15 +120,6 @@
|
||||
"queueingExport": "Antrean Ekspor...",
|
||||
"previewExport": "Pratinjau Ekspor",
|
||||
"useThisRange": "Gunakan Rentang Ini"
|
||||
},
|
||||
"stream": {
|
||||
"label": "Kualitas",
|
||||
"auto": "Otomatis",
|
||||
"main": "Asli",
|
||||
"sub": "Rendah",
|
||||
"autoDesc": "Menggunakan streaming utama dan beralih ke sub-stream berkualitas lebih rendah jika streaming utama tidak tersedia.",
|
||||
"mainDesc": "Mengekspor streaming utama dengan kualitas asli saja. Rentang waktu di mana streaming utama tidak tersedia akan terpotong.",
|
||||
"subDesc": "Mengekspor sub-stream berkualitas lebih rendah saja. Rentang waktu di mana sub-stream tidak tersedia akan terpotong."
|
||||
}
|
||||
},
|
||||
"search": {
|
||||
@@ -157,15 +147,14 @@
|
||||
"label": "Tampilkan statistik streaming",
|
||||
"desc": "Aktifkan opsi ini untuk menampilkan statistik streaming sebagai overlay pada tampilan kamera."
|
||||
},
|
||||
"debugView": "Tampilan Debug",
|
||||
"label": "Streaming"
|
||||
"debugView": "Tampilan Debug"
|
||||
},
|
||||
"recording": {
|
||||
"shareTimestamp": {
|
||||
"label": "Bagikan Cap Waktu",
|
||||
"title": "Bagikan Cap Waktu",
|
||||
"custom": "Cap Waktu Kustom",
|
||||
"button": "Bagikan URL Stempel Waktu",
|
||||
"button": "Bagikan URL Cap Waktu",
|
||||
"description": "Bagikan URL bertanda waktu sesuai posisi pemutar saat ini atau pilih tanda waktu kustom. Perlu dicatat bahwa ini bukan URL bagikan publik dan hanya dapat diakses oleh pengguna yang memiliki akses ke Frigate dan kamera ini.",
|
||||
"shareTitle": "Pratinjau Penunjuk Waktu Frigate : {{camera}}"
|
||||
},
|
||||
@@ -183,18 +172,11 @@
|
||||
"export": "Ekspor",
|
||||
"markAsReviewed": "Tandai sebagai sudah ditinjau",
|
||||
"markAsUnreviewed": "Tandai sebagai belum ditinjau",
|
||||
"deleteNow": "Hapus Sekarang",
|
||||
"generateDescription": "Buat deskripsi"
|
||||
},
|
||||
"genaiDescription": {
|
||||
"toast": {
|
||||
"success": "Deskripsi AI Generatif telah diminta untuk item tinjauan ini.",
|
||||
"error": "Gagal meminta deskripsi: {{error}}"
|
||||
}
|
||||
"deleteNow": "Hapus Sekarang"
|
||||
}
|
||||
},
|
||||
"imagePicker": {
|
||||
"selectImage": "Pilih miniatur objek yang dilacak",
|
||||
"selectImage": "Pilih gambar mini objek yang dilacak.",
|
||||
"unknownLabel": "Gambar Pemicu Tersimpan",
|
||||
"search": {
|
||||
"placeholder": "Cari berdasarkan label atau sub-label..."
|
||||
|
||||
@@ -51,8 +51,7 @@
|
||||
"hasSnapshot": "Memiliki Cuplikan",
|
||||
"hasVideoClip": "Memiliki Klip Video",
|
||||
"submittedToFrigatePlus": {
|
||||
"label": "Dikirim ke Frigate+",
|
||||
"tips": "Anda harus menyaring objek terlacak yang memiliki cuplikan (snapshot) terlebih dahulu.<br /><br />Objek terlacak tanpa cuplikan tidak dapat dikirimkan ke Frigate+."
|
||||
"label": "Dikirim ke Frigate+"
|
||||
}
|
||||
},
|
||||
"cameras": {
|
||||
@@ -82,59 +81,8 @@
|
||||
"settings": {
|
||||
"title": "Pengaturan",
|
||||
"defaultView": {
|
||||
"title": "Tampilan Default",
|
||||
"desc": "Bila tidak ada filter yang dipilih, tampilkan ringkasan objek teracak terbaru untuk setiap label, atau tampilkan kisi tanpa filter.",
|
||||
"summary": "Ringkasan",
|
||||
"unfilteredGrid": "Kisi Tanpa Filter"
|
||||
},
|
||||
"gridColumns": {
|
||||
"title": "Kolom Kisi",
|
||||
"desc": "Pilih jumlah kolom pada tampilan kisi."
|
||||
},
|
||||
"searchSource": {
|
||||
"label": "Sumber Pencarian",
|
||||
"desc": "Pilih apakah ingin mencari miniatur atau deskripsi dari objek yang dilacak.",
|
||||
"options": {
|
||||
"thumbnailImage": "Gambar Thumbnail",
|
||||
"description": "Deskripsi"
|
||||
}
|
||||
}
|
||||
},
|
||||
"date": {
|
||||
"selectDateBy": {
|
||||
"label": "Pilih tanggal untuk memfilter"
|
||||
"title": "Tampilan Default"
|
||||
}
|
||||
}
|
||||
},
|
||||
"logSettings": {
|
||||
"label": "Filter Log Level",
|
||||
"filterBySeverity": "Filter log berdasarkan tingkat keparahan",
|
||||
"loading": {
|
||||
"title": "Memuat",
|
||||
"desc": "Saat panel log digulir ke paling bawah, log baru akan otomatis di-stream seiring ditambahkan."
|
||||
},
|
||||
"disableLogStreaming": "Nonaktifkan streaming log",
|
||||
"allLogs": "Semua Log"
|
||||
},
|
||||
"trackedObjectDelete": {
|
||||
"title": "Konfirmasi Hapus",
|
||||
"desc": "Menghapus {{objectLength}} objek yang dilacak ini akan menghapus snapshot, embedding yang tersimpan, dan entri siklus hidup objek yang terkait. Rekaman video dari objek yang dilacak ini di tampilan History <em>TIDAK</em> akan dihapus.<br /><br />Apakah Anda yakin ingin melanjutkan?<br /><br />Tahan tombol <em>Shift</em> untuk melewati dialog ini di masa mendatang.",
|
||||
"toast": {
|
||||
"success": "Objek yang dilacak berhasil dihapus.",
|
||||
"error": "Gagal menghapus objek yang dilacak: {{errorMessage}}"
|
||||
}
|
||||
},
|
||||
"zoneMask": {
|
||||
"filterBy": "Filter berdasarkan zone mask"
|
||||
},
|
||||
"recognizedLicensePlates": {
|
||||
"title": "Plat Nomor yang Terkenali",
|
||||
"loadFailed": "Gagal memuat plat nomor yang dikenali.",
|
||||
"loading": "Memuat plat nomor yang dikenali…",
|
||||
"placeholder": "Ketik untuk mencari plat nomor…",
|
||||
"noLicensePlatesFound": "Plat nomor tidak ditemukan.",
|
||||
"selectPlatesFromList": "Pilih satu atau beberapa plat nomor dari daftar.",
|
||||
"selectAll": "Pilih semua",
|
||||
"clearAll": "Hapus semua"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,7 @@
|
||||
"noPreviewFoundFor": "Tidak ada Pratinjau untuk {{cameraName}}",
|
||||
"submitFrigatePlus": {
|
||||
"submit": "Kirim",
|
||||
"title": "Kirim frame ini ke Frigate+?",
|
||||
"previewError": "Gagal memuat pratinjau snapshot. Rekaman mungkin tidak tersedia saat ini."
|
||||
"title": "Kirim frame ini ke Frigate+?"
|
||||
},
|
||||
"noRecordingsFoundForThisTime": "Tidak ada rekaman ditemukan pada waktu ini",
|
||||
"livePlayerRequiredIOSVersion": "iOS 17.1 atau yang lebih tinggi diperlukan untuk tipe siaran langsung ini.",
|
||||
@@ -21,6 +20,14 @@
|
||||
"title": "Bandwith:",
|
||||
"short": "Bandwith"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latensi:",
|
||||
"value": "{{seconds}} detik",
|
||||
"short": {
|
||||
"title": "Latensi",
|
||||
"value": "{{seconds}} detik"
|
||||
}
|
||||
},
|
||||
"totalFrames": "Total Frame:",
|
||||
"droppedFrames": {
|
||||
"title": "Frame Terbuang:",
|
||||
@@ -29,7 +36,7 @@
|
||||
"value": "{{droppedFrames}} frame"
|
||||
}
|
||||
},
|
||||
"decodedFrames": "Bingkai yang Didekode:",
|
||||
"decodedFrames": "Decoded Frames:",
|
||||
"droppedFrameRate": "Frame Rate Terbuang:"
|
||||
},
|
||||
"toast": {
|
||||
@@ -37,23 +44,7 @@
|
||||
"submittedFrigatePlus": "Berhasil mengirim frame ke Frigate+"
|
||||
},
|
||||
"error": {
|
||||
"submitFrigatePlusFailed": "Gagal mengirim frame ke Frigate+",
|
||||
"playRecordingsFailed": "Gagal memutar rekaman (galat {{code}}): {{message}}"
|
||||
"submitFrigatePlusFailed": "Gagal mengirim frame ke Frigate+"
|
||||
}
|
||||
},
|
||||
"cameraOff": "Kamera mati",
|
||||
"quality": {
|
||||
"auto": "Otomatis",
|
||||
"autoLow": "Memutar kualitas rendah (bandwidth terbatas)",
|
||||
"autoLowCodec": "Memutar kualitas rendah (Versi asli tidak didukung oleh browser ini)",
|
||||
"autoLowSaveData": "Memutar kualitas rendah (penghemat data)",
|
||||
"main": "Asli",
|
||||
"sub": "Rendah",
|
||||
"notSupportedBrowser": "Tidak didukung oleh browser ini",
|
||||
"label": "Kualitas",
|
||||
"noAudio": "Tanpa suara",
|
||||
"audioRate": "Audio {{rate}} kHz",
|
||||
"audioCodecRate": "{{codec}} {{rate}} kHz",
|
||||
"noRecordings": "Tidak ada rekaman dalam rentang waktu ini"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,114 +17,36 @@
|
||||
},
|
||||
"filters": {
|
||||
"threshold": {
|
||||
"label": "Keyakinan-Suara Minimum",
|
||||
"description": "Ambang batas keyakinan minimum agar peristiwa audio dapat dihitung."
|
||||
},
|
||||
"label": "Filter audio",
|
||||
"description": "Pengaturan filter per-tipe-audio seperti ambang batas keyakinan yang digunakan untuk mengurangi hasil positif palsu."
|
||||
"label": "Keyakinan-Suara Minimum"
|
||||
}
|
||||
},
|
||||
"min_volume": {
|
||||
"label": "Volume-Suara Minimum",
|
||||
"description": "Ambang batas volume RMS minimum yang diperlukan untuk menjalankan deteksi audio; nilai yang lebih rendah meningkatkan sensitivitas (misalnya, 200 tinggi, 500 sedang, 1000 rendah)."
|
||||
},
|
||||
"max_not_heard": {
|
||||
"label": "Waktu habis berakhir",
|
||||
"description": "Jumlah detik tanpa tipe audio yang dikonfigurasi sebelum peristiwa audio diakhiri."
|
||||
},
|
||||
"listen": {
|
||||
"label": "Tipe pendengaran",
|
||||
"description": "Daftar tipe peristiwa audio yang akan dideteksi (sebagai contoh: gonggongan, alarm_kebakaran, ucapan, teriakan)."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "Kustomisasi peta label audio",
|
||||
"description": "Entri penimpaan atau pemetaan ulang untuk digabungkan ke dalam peta label audio standar."
|
||||
},
|
||||
"enabled_in_config": {
|
||||
"label": "Status audio asli",
|
||||
"description": "Menunjukkan apakah deteksi audio pada awalnya diaktifkan dalam berkas konfigurasi statis."
|
||||
},
|
||||
"num_threads": {
|
||||
"label": "Utas deteksi",
|
||||
"description": "Jumlah utas yang digunakan untuk pemrosesan deteksi audio."
|
||||
"label": "Volume-Suara Minimum"
|
||||
}
|
||||
},
|
||||
"audio_transcription": {
|
||||
"label": "Transkripsi Suara",
|
||||
"enabled": {
|
||||
"label": "Nyalakan Transkripsi",
|
||||
"description": "Aktifkan atau nonaktifkan transkripsi peristiwa audio yang dipicu secara manual."
|
||||
"label": "Nyalakan Transkripsi"
|
||||
},
|
||||
"live_enabled": {
|
||||
"label": "Transkripsi Langsung (Live)",
|
||||
"description": "Aktifkan streaming transkripsi langsung untuk audio saat diterima."
|
||||
},
|
||||
"description": "Pengaturan untuk transkripsi audio langsung dan ucapan yang digunakan untuk peristiwa dan teks langsung.",
|
||||
"enabled_in_config": {
|
||||
"label": "Status transkripsi asli"
|
||||
"label": "Transkripsi Langsung (Live)"
|
||||
}
|
||||
},
|
||||
"detect": {
|
||||
"label": "Deteksi Objek",
|
||||
"enabled": {
|
||||
"label": "Nyalakan Deteksi Objek",
|
||||
"description": "Aktifkan atau nonaktifkan deteksi objek untuk kamera ini."
|
||||
"label": "Nyalakan Deteksi Objek"
|
||||
},
|
||||
"stationary": {
|
||||
"classifier": {
|
||||
"label": "Nyalakan Klasifikasi-Visual",
|
||||
"description": "Menggunakan pengklasifikasi visual untuk membedakan objek-objek diam (benar-benar tidak bergerak), meskipun bounding-box kurang stabil atau bergetar (jitter)."
|
||||
},
|
||||
"label": "Konfigurasi objek diam",
|
||||
"description": "Pengaturan untuk mendeteksi dan mengelola objek yang tetap diam selama jangka waktu tertentu.",
|
||||
"interval": {
|
||||
"label": "Interval objek diam",
|
||||
"description": "Seberapa sering (dalam bingkai) untuk menjalankan pemeriksaan deteksi guna mengonfirmasi objek yang diam."
|
||||
},
|
||||
"threshold": {
|
||||
"label": "Ambang batas objek diam",
|
||||
"description": "Jumlah bingkai tanpa perubahan posisi yang diperlukan untuk menandai suatu objek sebagai objek diam."
|
||||
},
|
||||
"max_frames": {
|
||||
"label": "Maksimum bingkai",
|
||||
"description": "Membatasi berapa lama objek diam dilacak sebelum dibuang.",
|
||||
"default": {
|
||||
"label": "Maksimum bingkai bawaan (*default*)",
|
||||
"description": "Jumlah maksimum bingkai bawaan (*default*) untuk melacak objek diam sebelum dihentikan."
|
||||
},
|
||||
"objects": {
|
||||
"label": "Maksimum bingkai objek",
|
||||
"description": "Pengecualian (*override*) per-objek untuk maksimum bingkai guna melacak objek diam."
|
||||
}
|
||||
}
|
||||
},
|
||||
"fps": {
|
||||
"label": "Kecepatan (FPS) Deteksi",
|
||||
"description": "Kecepatan yang ditargetkan untuk menjalankan Deteksi Objek, dalam satuan frame per second (FPS); nilai lebih rendah mengurangi intensitas proses dan dapat meringangkan beban kerja CPU. Nilai 5 direkomendasikan, sedangakan nilai 10 dianggap sangat tinggi dan hanya digunakan untuk pelacakan (tracking) benda yang bergerak dengan benar-benar cepat."
|
||||
},
|
||||
"description": "Pengaturan untuk peran deteksi/detect yang digunakan untuk menjalankan deteksi objek dan menginisialisasi pelacak.",
|
||||
"height": {
|
||||
"label": "Tinggi deteksi",
|
||||
"description": "Tinggi (piksel) bingkai yang digunakan untuk alur deteksi; biarkan kosong untuk menggunakan resolusi alur asli."
|
||||
},
|
||||
"width": {
|
||||
"label": "Lebar deteksi",
|
||||
"description": "Lebar (piksel) bingkai yang digunakan untuk alur deteksi; biarkan kosong untuk menggunakan resolusi alur asli."
|
||||
},
|
||||
"scene": {
|
||||
"label": "Deteksi adegan",
|
||||
"description": "Lingkungan yang dilihat oleh kamera ini, digunakan untuk memilih mana dari model terkonfigurasi yang berjalan padanya. Kamera yang dibiarkan pada 'semua' akan menjalankan model yang dikonfigurasi dengan adegan 'semua'."
|
||||
},
|
||||
"min_initialized": {
|
||||
"label": "Jumlah minimum bingkai inisialisasi",
|
||||
"description": "Jumlah *detection hit* berturut-turut yang diperlukan sebelum membuat objek yang dilacak. Tingkatkan untuk mengurangi inisialisasi palsu. Nilai bawaan (*default*) adalah fps dibagi 2."
|
||||
},
|
||||
"max_disappeared": {
|
||||
"label": "Jumlah maksimum bingkai yang hilang",
|
||||
"description": "Jumlah bingkai tanpa deteksi sebelum objek yang dilacak dianggap hilang."
|
||||
},
|
||||
"annotation_offset": {
|
||||
"label": "Persetan anotasi (*annotation offset*)",
|
||||
"description": "Milisikron (milidetik) untuk menggeser anotasi deteksi agar kotak pembatas (*bounding box*) pada garis waktu lebih sejajar dengan rekaman; dapat bernilai positif atau negatif."
|
||||
}
|
||||
},
|
||||
"enabled": {
|
||||
@@ -135,176 +57,6 @@
|
||||
"enabled": {
|
||||
"description": "Nyalakan atau matikan fitur Penglihatan Atas (Birdseye View).",
|
||||
"label": "Nyalakan Birdseye"
|
||||
},
|
||||
"label": "Pandangan mata burung",
|
||||
"description": "Pengaturan untuk tampilan komposit Birdseye yang menggabungkan beberapa umpan kamera ke dalam satu tata letak.",
|
||||
"modes": {
|
||||
"label": "Tipe aktivitas",
|
||||
"description": "Tipe aktivitas yang mencakup kamera dalam pandangan Birdseye."
|
||||
},
|
||||
"order": {
|
||||
"label": "Posisi",
|
||||
"description": "Posisi numerik yang mengatur urutan kamera dalam tata letak Birdseye."
|
||||
}
|
||||
},
|
||||
"face_recognition": {
|
||||
"label": "Pengenalan wajah (*face recognition*)",
|
||||
"description": "Pengaturan untuk deteksi dan pengenalan wajah pada kamera ini.",
|
||||
"enabled": {
|
||||
"label": "Aktifkan pengenalan wajah (*enable face recognition*)",
|
||||
"description": "Mengaktifkan atau mematikan pengenalan wajah."
|
||||
},
|
||||
"min_area": {
|
||||
"label": "Area wajah minimum",
|
||||
"description": "Luas minimum (dalam piksel) dari kotak wajah yang terdeteksi yang diperlukan untuk mencoba pengenalan."
|
||||
}
|
||||
},
|
||||
"ffmpeg": {
|
||||
"label": "Stream (FFmpeg)",
|
||||
"description": "Input stream kamera dan opsi FFmpeg, termasuk path binary, parameter, hwaccel, dan parameter output per-role.",
|
||||
"path": {
|
||||
"label": "Path FFmpeg",
|
||||
"description": "Path ke binary FFmpeg yang digunakan atau alias versi (\"7.0\" or \"8.0\")."
|
||||
},
|
||||
"global_args": {
|
||||
"label": "Parameter global FFmpeg",
|
||||
"description": "Parameter global yang dikirim ke proses FFmpeg."
|
||||
},
|
||||
"hwaccel_args": {
|
||||
"label": "Parameter akselerasi hardware",
|
||||
"description": "Parameter akselerasi hardware untuk FFmpeg. Preset khusus provider direkomendasikan."
|
||||
},
|
||||
"input_args": {
|
||||
"label": "Parameter input",
|
||||
"description": "Parameter input yang diterapkan ke stream input FFmpeg."
|
||||
},
|
||||
"output_args": {
|
||||
"label": "Parameter output",
|
||||
"description": "Parameter output default yang digunakan untuk berbagai role FFmpeg seperti detect dan record.",
|
||||
"detect": {
|
||||
"label": "Parameter output detect",
|
||||
"description": "Parameter output default untuk stream role detect."
|
||||
},
|
||||
"record": {
|
||||
"label": "Parameter output record",
|
||||
"description": "Parameter output default untuk stream role record."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "Parameter output record sub stream",
|
||||
"description": "Parameter output untuk stream peran record_sub. Parameter output record akan digunakan jika opsi ini tidak diatur."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
"label": "Waktu coba ulang FFmpeg",
|
||||
"description": "Jumlah detik untuk menunggu sebelum mencoba menghubungkan ulang stream kamera setelah gagal. Default adalah 10."
|
||||
},
|
||||
"apple_compatibility": {
|
||||
"label": "Kompatibilitas Apple",
|
||||
"description": "Aktifkan penandaan HEVC untuk kompatibilitas player Apple yang lebih baik saat merekam H.265."
|
||||
},
|
||||
"gpu": {
|
||||
"label": "Index GPU",
|
||||
"description": "Index GPU default yang digunakan untuk akselerasi hardware jika tersedia."
|
||||
},
|
||||
"inputs": {
|
||||
"label": "Input kamera",
|
||||
"description": "Daftar definisi stream input (path dan peran) untuk kamera ini.",
|
||||
"path": {
|
||||
"label": "Path input",
|
||||
"description": "URL atau path stream input kamera."
|
||||
},
|
||||
"roles": {
|
||||
"label": "Peran input",
|
||||
"description": "Peran untuk stream input ini."
|
||||
},
|
||||
"global_args": {
|
||||
"label": "Parameter global FFmpeg",
|
||||
"description": "Parameter global FFmpeg untuk stream input ini."
|
||||
},
|
||||
"hwaccel_args": {
|
||||
"label": "Argument akselerasi hardware",
|
||||
"description": "Parameter akselerasi hardware untuk stream input ini."
|
||||
},
|
||||
"input_args": {
|
||||
"label": "Parameter input",
|
||||
"description": "Parameter input khusus untuk stream ini."
|
||||
}
|
||||
}
|
||||
},
|
||||
"live": {
|
||||
"label": "Pemutaran langsung",
|
||||
"description": "Pengaturan yang digunakan oleh Web UI untuk mengontrol pemilihan, resolusi, dan kualitas live stream.",
|
||||
"streams": {
|
||||
"label": "Nama stream langsung",
|
||||
"description": "Pemetaan nama stream terkonfigurasi ke nama restream/go2rtc yang digunakan untuk pemutaran langsung."
|
||||
},
|
||||
"height": {
|
||||
"label": "Tinggi pemutaran langsung",
|
||||
"description": "Tinggi (piksel) untuk merender live stream jsmpeg di Web UI; harus <= tinggi stream detect."
|
||||
},
|
||||
"quality": {
|
||||
"label": "Kualitas pemutaran langsung",
|
||||
"description": "Kualitas encoding untuk stream jsmpeg (1 tertinggi, 31 terendah)."
|
||||
}
|
||||
},
|
||||
"lpr": {
|
||||
"label": "Pengenalan Plat Nomor",
|
||||
"description": "Pengaturan pengenalan plat nomor termasuk ambang batas deteksi, format, dan plat yang dikenal.",
|
||||
"enabled": {
|
||||
"label": "Aktifkan LPR",
|
||||
"description": "Aktifkan atau nonaktifkan LPR pada kamera ini."
|
||||
},
|
||||
"expire_time": {
|
||||
"label": "Waktu kadaluarsa dalam detik",
|
||||
"description": "Waktu dalam detik setelah plat yang tidak terlihat kadaluarsa dari pelacak (hanya untuk kamera LPR khusus)."
|
||||
},
|
||||
"min_area": {
|
||||
"label": "Luas area plat minimum",
|
||||
"description": "Luas area plat minimum (piksel) yang diperlukan untuk mencoba pengenalan."
|
||||
},
|
||||
"enhancement": {
|
||||
"label": "Level peningkatan",
|
||||
"description": "Tingkat peningkatan (0–10) yang diterapkan pada potongan gambar plat sebelum OCR. Nilai yang lebih tinggi tidak selalu memberikan hasil yang lebih baik; level di atas 5 umumnya hanya efektif untuk plat di malam hari dan sebaiknya digunakan secara hati-hati."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "Deteksi gerakan",
|
||||
"description": "Pengaturan deteksi gerakan bawaan untuk kamera ini.",
|
||||
"enabled": {
|
||||
"label": "Aktifkan deteksi gerakan",
|
||||
"description": "Aktifkan atau nonaktifkan deteksi gerakan untuk kamera ini."
|
||||
},
|
||||
"threshold": {
|
||||
"label": "Ambang batas gerakan",
|
||||
"description": "Ambang batas perbedaan piksel yang digunakan oleh detektor gerakan; nilai yang lebih tinggi akan mengurangi sensitivitas (rentang 1–255)."
|
||||
},
|
||||
"lightning_threshold": {
|
||||
"label": "Ambang batas pencahayaan",
|
||||
"description": "Ambang batas untuk mendeteksi dan mengabaikan lonjakan pencahayaan singkat (nilai lebih rendah berarti lebih sensitif, rentang antara 0,3 hingga 1,0). Hal ini tidak menghentikan deteksi gerakan secara total, melainkan hanya membuat detektor berhenti menganalisis bingkai (frame) tambahan setelah ambang batas terlampaui. Rekaman berbasis gerakan akan tetap dibuat selama peristiwa ini terjadi."
|
||||
},
|
||||
"skip_motion_threshold": {
|
||||
"label": "Lewati ambang batas gerakan",
|
||||
"description": "Jika diatur ke nilai antara 0.0 dan 1.0, dan perubahan dalam satu bingkai (frame) melebihi fraksi ini, detektor tidak akan menampilkan kotak gerakan dan langsung melakukan kalibrasi ulang. Hal ini dapat menghemat CPU serta mengurangi hasil positif palsu saat terjadi petir, badai, dll., namun berisiko melewatkan kejadian nyata seperti kamera PTZ yang memantau objek secara otomatis. Pilihan ini adalah kompromi antara kehilangan beberapa megabita rekaman versus memeriksa beberapa klip pendek. Biarkan kosong (None) untuk menonaktifkan fitur ini."
|
||||
},
|
||||
"improve_contrast": {
|
||||
"label": "Tingkatkan kontras",
|
||||
"description": "Terapkan peningkatan kontras pada bingkai (frame) sebelum analisis gerakan untuk membantu proses deteksi."
|
||||
},
|
||||
"contour_area": {
|
||||
"label": "Area kontur",
|
||||
"description": "Area kontur minimum dalam piksel yang diperlukan agar kontur gerakan dapat terhitung."
|
||||
},
|
||||
"delta_alpha": {
|
||||
"label": "motion.delta_alpha.label",
|
||||
"description": "Faktor pembauran alfa (*alpha blending*) yang digunakan dalam komparasi bingkai (*frame differencing*) untuk kalkulasi gerakan."
|
||||
},
|
||||
"frame_alpha": {
|
||||
"label": "Frame alfa",
|
||||
"description": "Nilai alfa yang digunakan saat membaurkan bingkai (*frame blending*) untuk pra-pemrosesan gerakan."
|
||||
},
|
||||
"frame_height": {
|
||||
"label": "Tinggi bingkai",
|
||||
"description": "Tinggi dalam piksel untuk mengubah skala bingkai (*frame*) saat menghitung gerakan."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,44 +9,18 @@
|
||||
},
|
||||
"filters": {
|
||||
"threshold": {
|
||||
"label": "Keyakinan-Suara Minimum",
|
||||
"description": "Ambang batas keyakinan minimum agar peristiwa audio dapat dihitung."
|
||||
},
|
||||
"label": "Filter audio",
|
||||
"description": "Pengaturan filter per-tipe-audio seperti ambang batas keyakinan yang digunakan untuk mengurangi hasil positif palsu."
|
||||
"label": "Keyakinan-Suara Minimum"
|
||||
}
|
||||
},
|
||||
"min_volume": {
|
||||
"label": "Volume-Suara Minimum",
|
||||
"description": "Ambang batas volume RMS minimum yang diperlukan untuk menjalankan deteksi audio; nilai yang lebih rendah meningkatkan sensitivitas (misalnya, 200 tinggi, 500 sedang, 1000 rendah)."
|
||||
},
|
||||
"max_not_heard": {
|
||||
"label": "Waktu habis berakhir",
|
||||
"description": "Jumlah detik tanpa tipe audio yang dikonfigurasi sebelum peristiwa audio diakhiri."
|
||||
},
|
||||
"listen": {
|
||||
"label": "Tipe pendengaran",
|
||||
"description": "Daftar tipe peristiwa audio yang akan dideteksi (sebagai contoh: gonggongan, alarm_kebakaran, ucapan, teriakan)."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "Kustomisasi peta label audio",
|
||||
"description": "Entri penimpaan atau pemetaan ulang untuk digabungkan ke dalam peta label audio standar."
|
||||
},
|
||||
"enabled_in_config": {
|
||||
"label": "Status audio asli",
|
||||
"description": "Menunjukkan apakah deteksi audio pada awalnya diaktifkan dalam berkas konfigurasi statis."
|
||||
},
|
||||
"num_threads": {
|
||||
"label": "Utas deteksi",
|
||||
"description": "Jumlah utas yang digunakan untuk pemrosesan deteksi audio."
|
||||
"label": "Volume-Suara Minimum"
|
||||
}
|
||||
},
|
||||
"audio_transcription": {
|
||||
"label": "Transkripsi Suara",
|
||||
"live_enabled": {
|
||||
"label": "Transkripsi Langsung (Live)",
|
||||
"description": "Aktifkan streaming transkripsi langsung untuk audio saat diterima."
|
||||
},
|
||||
"description": "Pengaturan untuk transkripsi audio langsung dan ucapan yang digunakan untuk peristiwa dan teks langsung."
|
||||
"label": "Transkripsi Langsung (Live)"
|
||||
}
|
||||
},
|
||||
"detect": {
|
||||
"label": "Deteksi Objek",
|
||||
@@ -57,226 +31,17 @@
|
||||
"classifier": {
|
||||
"label": "Nyalakan Klasifikasi-Visual",
|
||||
"description": "Menggunakan pengklasifikasi visual untuk membedakan objek-objek diam (benar-benar tidak bergerak), meskipun bounding-box kurang stabil atau bergetar (jitter)."
|
||||
},
|
||||
"label": "Konfigurasi objek diam",
|
||||
"description": "Pengaturan untuk mendeteksi dan mengelola objek yang tetap diam selama jangka waktu tertentu.",
|
||||
"interval": {
|
||||
"label": "Interval objek diam",
|
||||
"description": "Seberapa sering (dalam bingkai) untuk menjalankan pemeriksaan deteksi guna mengonfirmasi objek yang diam."
|
||||
},
|
||||
"threshold": {
|
||||
"label": "Ambang batas objek diam",
|
||||
"description": "Jumlah bingkai tanpa perubahan posisi yang diperlukan untuk menandai suatu objek sebagai objek diam."
|
||||
},
|
||||
"max_frames": {
|
||||
"label": "Maksimum bingkai",
|
||||
"description": "Membatasi berapa lama objek diam dilacak sebelum dibuang.",
|
||||
"default": {
|
||||
"label": "Maksimum bingkai bawaan (*default*)",
|
||||
"description": "Jumlah maksimum bingkai bawaan (*default*) untuk melacak objek diam sebelum dihentikan."
|
||||
},
|
||||
"objects": {
|
||||
"label": "Maksimum bingkai objek",
|
||||
"description": "Pengecualian (*override*) per-objek untuk maksimum bingkai guna melacak objek diam."
|
||||
}
|
||||
}
|
||||
},
|
||||
"fps": {
|
||||
"label": "Kecepatan (FPS) Deteksi",
|
||||
"description": "Kecepatan yang ditargetkan untuk menjalankan Deteksi Objek, dalam satuan frame per second (FPS); nilai lebih rendah mengurangi intensitas proses dan dapat meringangkan beban kerja CPU. Nilai 5 direkomendasikan, sedangakan nilai 10 dianggap sangat tinggi dan hanya digunakan untuk pelacakan (tracking) benda yang bergerak dengan benar-benar cepat."
|
||||
},
|
||||
"description": "Pengaturan untuk peran deteksi/detect yang digunakan untuk menjalankan deteksi objek dan menginisialisasi pelacak.",
|
||||
"height": {
|
||||
"label": "Tinggi deteksi",
|
||||
"description": "Tinggi (piksel) bingkai yang digunakan untuk alur deteksi; biarkan kosong untuk menggunakan resolusi alur asli."
|
||||
},
|
||||
"width": {
|
||||
"label": "Lebar deteksi",
|
||||
"description": "Lebar (piksel) bingkai yang digunakan untuk alur deteksi; biarkan kosong untuk menggunakan resolusi alur asli."
|
||||
},
|
||||
"scene": {
|
||||
"label": "Deteksi adegan",
|
||||
"description": "Lingkungan yang dilihat oleh kamera ini, digunakan untuk memilih mana dari model terkonfigurasi yang berjalan padanya. Kamera yang dibiarkan pada 'semua' akan menjalankan model yang dikonfigurasi dengan adegan 'semua'."
|
||||
},
|
||||
"min_initialized": {
|
||||
"label": "Jumlah minimum bingkai inisialisasi",
|
||||
"description": "Jumlah *detection hit* berturut-turut yang diperlukan sebelum membuat objek yang dilacak. Tingkatkan untuk mengurangi inisialisasi palsu. Nilai bawaan (*default*) adalah fps dibagi 2."
|
||||
},
|
||||
"max_disappeared": {
|
||||
"label": "Jumlah maksimum bingkai yang hilang",
|
||||
"description": "Jumlah bingkai tanpa deteksi sebelum objek yang dilacak dianggap hilang."
|
||||
},
|
||||
"annotation_offset": {
|
||||
"label": "Persetan anotasi (*annotation offset*)",
|
||||
"description": "Milisikron (milidetik) untuk menggeser anotasi deteksi agar kotak pembatas (*bounding box*) pada garis waktu lebih sejajar dengan rekaman; dapat bernilai positif atau negatif."
|
||||
}
|
||||
},
|
||||
"birdseye": {
|
||||
"enabled": {
|
||||
"description": "Nyalakan atau matikan fitur Penglihatan Atas (Birdseye View).",
|
||||
"label": "Nyalakan Birdseye"
|
||||
},
|
||||
"label": "Pandangan mata burung",
|
||||
"description": "Pengaturan untuk tampilan komposit Birdseye yang menggabungkan beberapa umpan kamera ke dalam satu tata letak.",
|
||||
"modes": {
|
||||
"label": "Tipe aktivitas",
|
||||
"description": "Tipe aktivitas yang mencakup kamera dalam pandangan Birdseye."
|
||||
},
|
||||
"order": {
|
||||
"label": "Posisi",
|
||||
"description": "Posisi numerik yang mengatur urutan kamera dalam tata letak Birdseye."
|
||||
}
|
||||
},
|
||||
"face_recognition": {
|
||||
"label": "Pengenalan wajah (*face recognition*)",
|
||||
"enabled": {
|
||||
"label": "Aktifkan pengenalan wajah (*enable face recognition*)"
|
||||
},
|
||||
"min_area": {
|
||||
"label": "Area wajah minimum",
|
||||
"description": "Luas minimum (dalam piksel) dari kotak wajah yang terdeteksi yang diperlukan untuk mencoba pengenalan."
|
||||
}
|
||||
},
|
||||
"ffmpeg": {
|
||||
"path": {
|
||||
"label": "Path FFmpeg",
|
||||
"description": "Path ke binary FFmpeg yang digunakan atau alias versi (\"7.0\" or \"8.0\")."
|
||||
},
|
||||
"global_args": {
|
||||
"label": "Parameter global FFmpeg",
|
||||
"description": "Parameter global yang dikirim ke proses FFmpeg."
|
||||
},
|
||||
"hwaccel_args": {
|
||||
"label": "Parameter akselerasi hardware",
|
||||
"description": "Parameter akselerasi hardware untuk FFmpeg. Preset khusus provider direkomendasikan."
|
||||
},
|
||||
"input_args": {
|
||||
"label": "Parameter input",
|
||||
"description": "Parameter input yang diterapkan ke stream input FFmpeg."
|
||||
},
|
||||
"output_args": {
|
||||
"label": "Parameter output",
|
||||
"description": "Parameter output default yang digunakan untuk berbagai role FFmpeg seperti detect dan record.",
|
||||
"detect": {
|
||||
"label": "Parameter output detect",
|
||||
"description": "Parameter output default untuk stream role detect."
|
||||
},
|
||||
"record": {
|
||||
"label": "Parameter output record",
|
||||
"description": "Parameter output default untuk stream role record."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "Parameter output record sub stream",
|
||||
"description": "Parameter output untuk stream peran record_sub. Parameter output record akan digunakan jika opsi ini tidak diatur."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
"label": "Waktu coba ulang FFmpeg",
|
||||
"description": "Jumlah detik untuk menunggu sebelum mencoba menghubungkan ulang stream kamera setelah gagal. Default adalah 10."
|
||||
},
|
||||
"apple_compatibility": {
|
||||
"label": "Kompatibilitas Apple",
|
||||
"description": "Aktifkan penandaan HEVC untuk kompatibilitas player Apple yang lebih baik saat merekam H.265."
|
||||
},
|
||||
"gpu": {
|
||||
"label": "Index GPU",
|
||||
"description": "Index GPU default yang digunakan untuk akselerasi hardware jika tersedia."
|
||||
},
|
||||
"inputs": {
|
||||
"label": "Input kamera",
|
||||
"description": "Daftar definisi stream input (path dan peran) untuk kamera ini.",
|
||||
"path": {
|
||||
"label": "Path input",
|
||||
"description": "URL atau path stream input kamera."
|
||||
},
|
||||
"roles": {
|
||||
"label": "Peran input",
|
||||
"description": "Peran untuk stream input ini."
|
||||
},
|
||||
"global_args": {
|
||||
"label": "Parameter global FFmpeg",
|
||||
"description": "Parameter global FFmpeg untuk stream input ini."
|
||||
},
|
||||
"hwaccel_args": {
|
||||
"label": "Argument akselerasi hardware",
|
||||
"description": "Parameter akselerasi hardware untuk stream input ini."
|
||||
},
|
||||
"input_args": {
|
||||
"label": "Parameter input",
|
||||
"description": "Parameter input khusus untuk stream ini."
|
||||
}
|
||||
}
|
||||
},
|
||||
"live": {
|
||||
"label": "Pemutaran langsung",
|
||||
"streams": {
|
||||
"label": "Nama stream langsung",
|
||||
"description": "Pemetaan nama stream terkonfigurasi ke nama restream/go2rtc yang digunakan untuk pemutaran langsung."
|
||||
},
|
||||
"height": {
|
||||
"label": "Tinggi pemutaran langsung",
|
||||
"description": "Tinggi (piksel) untuk merender live stream jsmpeg di Web UI; harus <= tinggi stream detect."
|
||||
},
|
||||
"quality": {
|
||||
"label": "Kualitas pemutaran langsung",
|
||||
"description": "Kualitas encoding untuk stream jsmpeg (1 tertinggi, 31 terendah)."
|
||||
}
|
||||
},
|
||||
"lpr": {
|
||||
"label": "Pengenalan Plat Nomor",
|
||||
"description": "Pengaturan pengenalan plat nomor termasuk ambang batas deteksi, format, dan plat yang dikenal.",
|
||||
"enabled": {
|
||||
"label": "Aktifkan LPR"
|
||||
},
|
||||
"expire_time": {
|
||||
"label": "Waktu kadaluarsa dalam detik",
|
||||
"description": "Waktu dalam detik setelah plat yang tidak terlihat kadaluarsa dari pelacak (hanya untuk kamera LPR khusus)."
|
||||
},
|
||||
"min_area": {
|
||||
"label": "Luas area plat minimum",
|
||||
"description": "Luas area plat minimum (piksel) yang diperlukan untuk mencoba pengenalan."
|
||||
},
|
||||
"enhancement": {
|
||||
"label": "Level peningkatan",
|
||||
"description": "Tingkat peningkatan (0–10) yang diterapkan pada potongan gambar plat sebelum OCR. Nilai yang lebih tinggi tidak selalu memberikan hasil yang lebih baik; level di atas 5 umumnya hanya efektif untuk plat di malam hari dan sebaiknya digunakan secara hati-hati."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "Deteksi gerakan",
|
||||
"enabled": {
|
||||
"label": "Aktifkan deteksi gerakan"
|
||||
},
|
||||
"threshold": {
|
||||
"label": "Ambang batas gerakan",
|
||||
"description": "Ambang batas perbedaan piksel yang digunakan oleh detektor gerakan; nilai yang lebih tinggi akan mengurangi sensitivitas (rentang 1–255)."
|
||||
},
|
||||
"lightning_threshold": {
|
||||
"label": "Ambang batas pencahayaan",
|
||||
"description": "Ambang batas untuk mendeteksi dan mengabaikan lonjakan pencahayaan singkat (nilai lebih rendah berarti lebih sensitif, rentang antara 0,3 hingga 1,0). Hal ini tidak menghentikan deteksi gerakan secara total, melainkan hanya membuat detektor berhenti menganalisis bingkai (frame) tambahan setelah ambang batas terlampaui. Rekaman berbasis gerakan akan tetap dibuat selama peristiwa ini terjadi."
|
||||
},
|
||||
"skip_motion_threshold": {
|
||||
"label": "Lewati ambang batas gerakan",
|
||||
"description": "Jika diatur ke nilai antara 0.0 dan 1.0, dan perubahan dalam satu bingkai (frame) melebihi fraksi ini, detektor tidak akan menampilkan kotak gerakan dan langsung melakukan kalibrasi ulang. Hal ini dapat menghemat CPU serta mengurangi hasil positif palsu saat terjadi petir, badai, dll., namun berisiko melewatkan kejadian nyata seperti kamera PTZ yang memantau objek secara otomatis. Pilihan ini adalah kompromi antara kehilangan beberapa megabita rekaman versus memeriksa beberapa klip pendek. Biarkan kosong (None) untuk menonaktifkan fitur ini."
|
||||
},
|
||||
"improve_contrast": {
|
||||
"label": "Tingkatkan kontras",
|
||||
"description": "Terapkan peningkatan kontras pada bingkai (frame) sebelum analisis gerakan untuk membantu proses deteksi."
|
||||
},
|
||||
"contour_area": {
|
||||
"label": "Area kontur",
|
||||
"description": "Area kontur minimum dalam piksel yang diperlukan agar kontur gerakan dapat terhitung."
|
||||
},
|
||||
"delta_alpha": {
|
||||
"label": "motion.delta_alpha.label",
|
||||
"description": "Faktor pembauran alfa (*alpha blending*) yang digunakan dalam komparasi bingkai (*frame differencing*) untuk kalkulasi gerakan."
|
||||
},
|
||||
"frame_alpha": {
|
||||
"label": "Frame alfa",
|
||||
"description": "Nilai alfa yang digunakan saat membaurkan bingkai (*frame blending*) untuk pra-pemrosesan gerakan."
|
||||
},
|
||||
"frame_height": {
|
||||
"label": "Tinggi bingkai",
|
||||
"description": "Tinggi dalam piksel untuk mengubah skala bingkai (*frame*) saat menghitung gerakan."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -165,8 +165,8 @@
|
||||
"configuration": "Configurazione",
|
||||
"languages": "Lingue",
|
||||
"appearance": "Aspetto",
|
||||
"systemMetrics": "Salute e metriche",
|
||||
"systemLogs": "Registri",
|
||||
"systemMetrics": "Metriche di sistema",
|
||||
"systemLogs": "Registri di sistema",
|
||||
"settings": "Impostazioni",
|
||||
"configurationEditor": "Editor di configurazione",
|
||||
"language": {
|
||||
|
||||
@@ -66,9 +66,9 @@
|
||||
"batchSuccess_other": "Avviate {{count}} esportazioni. Apertura del caso in corso.",
|
||||
"batchPartial": "Avviate {{successful}} esportazioni su un totale di {{total}}. Telecamere non riuscite: {{failedCameras}}",
|
||||
"batchFailed": "Impossibile avviare {{total}} esportazioni. Telecamere non riuscite: {{failedCameras}}",
|
||||
"batchQueuedSuccess_one": "1 esportazione in coda.",
|
||||
"batchQueuedSuccess_many": "{{count}} esportazioni in coda.",
|
||||
"batchQueuedSuccess_other": "{{count}} esportazioni in coda.",
|
||||
"batchQueuedSuccess_one": "1 esportazione in coda. Apertura del caso in corso.",
|
||||
"batchQueuedSuccess_many": "Sono in coda {{count}} esportazioni. Apertura del caso in corso.",
|
||||
"batchQueuedSuccess_other": "Sono in coda {{count}} esportazioni. Apertura del caso in corso.",
|
||||
"batchQueuedPartial": "In coda {{successful}} di {{total}} esportazioni. Telecamere non riuscite: {{failedCameras}}",
|
||||
"batchQueueFailed": "Impossibile mettere in coda {{total}} esportazioni. Telecamere non riuscite: {{failedCameras}}"
|
||||
},
|
||||
@@ -131,9 +131,9 @@
|
||||
"exportButton_other": "Esporta {{count}} revisioni",
|
||||
"exportingButton": "Esportazione...",
|
||||
"toast": {
|
||||
"started_one": "Avviata 1 esportazione.",
|
||||
"started_many": "Avviate {{count}} esportazioni.",
|
||||
"started_other": "Avviate {{count}} esportazioni.",
|
||||
"started_one": "Avviata 1 esportazione. Apertura del caso in corso.",
|
||||
"started_many": "Avviate {{count}} esportazioni. Apertura del caso in corso.",
|
||||
"started_other": "Avviate {{count}} esportazioni. Apertura del caso in corso.",
|
||||
"partial": "Avviate {{successful}} esportazioni su un totale di {{total}}. Fallite: {{failedItems}}",
|
||||
"failed": "Impossibile avviare {{total}} esportazioni. Errori: {{failedItems}}"
|
||||
}
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
"title": "Larghezza di banda:",
|
||||
"short": "Larghezza di banda"
|
||||
},
|
||||
"latency": {
|
||||
"title": "Latenza:",
|
||||
"value": "{{seconds}} secondi",
|
||||
"short": {
|
||||
"title": "Latenza",
|
||||
"value": "{{seconds}} sec"
|
||||
}
|
||||
},
|
||||
"droppedFrames": {
|
||||
"title": "Fotogrammi persi:",
|
||||
"short": {
|
||||
|
||||
@@ -464,7 +464,7 @@
|
||||
},
|
||||
"default_role": {
|
||||
"label": "Ruolo predefinito",
|
||||
"description": "Ruolo predefinito assegnato agli utenti autenticati tramite proxy quando non è applicabile alcuna mappatura dei ruoli. Imposta su 'nessuno' per negare l'accesso agli utenti non mappati."
|
||||
"description": "Ruolo predefinito assegnato agli utenti autenticati tramite proxy quando non si applica nessuna mappatura dei ruoli."
|
||||
},
|
||||
"separator": {
|
||||
"label": "Carattere separatore",
|
||||
@@ -1399,8 +1399,5 @@
|
||||
"label": "Ordine di ordinamento",
|
||||
"description": "Ordine numerico utilizzato per ordinare i gruppi di telecamere nell'interfaccia utente; i numeri più alti appaiono dopo."
|
||||
}
|
||||
},
|
||||
"models": {
|
||||
"label": "Modelli di rilevamento"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -427,7 +427,7 @@
|
||||
"cameraMqtt": "MQTT telecamera",
|
||||
"maintenance": "Manutenzione",
|
||||
"regionGrid": "Griglia di regioni",
|
||||
"systemDetectorsAndModel": "Modelli di rilevamento"
|
||||
"systemDetectorsAndModel": "Rilevatori e modelli"
|
||||
},
|
||||
"users": {
|
||||
"dialog": {
|
||||
@@ -964,7 +964,7 @@
|
||||
},
|
||||
"cameraWizard": {
|
||||
"step3": {
|
||||
"description": "Configura le funzionalità, i ruoli dei flussi e aggiungi flussi supplementari per la tua telecamera.",
|
||||
"description": "Configura i ruoli del flusso e aggiungi altri flussi alla tua telecamera.",
|
||||
"streamTitle": "Flusso {{number}}",
|
||||
"roles": "Ruoli",
|
||||
"streamsTitle": "Flussi della telecamera",
|
||||
@@ -1940,8 +1940,5 @@
|
||||
"overrideGlobal": "Questa sezione sovrascrive la configurazione globale",
|
||||
"overrideProfile": "Questa sezione viene sovrascritta dal profilo {{profile}}",
|
||||
"unsaved": "Questa sezione contiene modifiche non salvate"
|
||||
},
|
||||
"detectionModels": {
|
||||
"title": "Modelli di rilevamento"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,14 @@
|
||||
"title": "帯域:",
|
||||
"short": "帯域幅"
|
||||
},
|
||||
"latency": {
|
||||
"title": "遅延:",
|
||||
"value": "{{seconds}} 秒",
|
||||
"short": {
|
||||
"title": "遅延",
|
||||
"value": "{{seconds}} 秒"
|
||||
}
|
||||
},
|
||||
"totalFrames": "総フレーム:",
|
||||
"droppedFrames": {
|
||||
"title": "ドロップしたフレーム:",
|
||||
|
||||
@@ -93,9 +93,9 @@
|
||||
"setPassword": "비밀번호 설정"
|
||||
},
|
||||
"system": "시스템",
|
||||
"systemMetrics": "시스템 상태와 지표",
|
||||
"systemMetrics": "시스템 지표",
|
||||
"configuration": "설정 구성",
|
||||
"systemLogs": "로그",
|
||||
"systemLogs": "시스템 로그",
|
||||
"settings": "설정",
|
||||
"configurationEditor": "설정 편집기",
|
||||
"languages": "언어",
|
||||
@@ -266,10 +266,7 @@
|
||||
"savingAll": "모두 저장 중…",
|
||||
"undoAll": "모두 실행 취소",
|
||||
"applying": "적용 중…",
|
||||
"retry": "재시도",
|
||||
"expand": "펼치기",
|
||||
"collapse": "접기",
|
||||
"reload": "새로고침"
|
||||
"retry": "재시도"
|
||||
},
|
||||
"toast": {
|
||||
"copyUrlToClipboard": "클립보드에 URL이 복사되었습니다.",
|
||||
@@ -317,36 +314,5 @@
|
||||
"validation_errors": "유효성 검사 오류",
|
||||
"credentialField": {
|
||||
"savedPlaceholder": "저장됨 — 현재 값을 유지하려면 비워 두세요"
|
||||
},
|
||||
"error": {
|
||||
"title": "이 페이지가 작동을 멈췄습니다",
|
||||
"desc": "페이지에 예기치 않은 오류가 발생했습니다. 일반적으로 새로고침하면 해결됩니다. 문제가 계속되면 세부 정보를 복사하여 GitHub Discussion에 첨부해 주세요.",
|
||||
"staleTitle": "새로고침 필요",
|
||||
"staleDesc": "인터페이스의 일부를 불러오지 못했습니다. 이 탭이 열려 있는 동안 Frigate이 업데이트되었을 수 있습니다. 최신 버전을 반영하려면 새로고침하세요.",
|
||||
"partial": "인터페이스의 일부가 작동을 멈췄습니다.",
|
||||
"copyDetails": "세부 정보 복사",
|
||||
"copyFailed": "세부 정보를 클립보드에 복사하지 못했습니다"
|
||||
},
|
||||
"commandMenu": {
|
||||
"title": "명령 메뉴",
|
||||
"description": "페이지, 카메라, 설정 및 작업 검색",
|
||||
"placeholder": "페이지, 카메라, 설정 및 작업 검색",
|
||||
"empty": "일치하는 항목 없음",
|
||||
"hint": "{{key}}로 열거나, 엔터키로 실행",
|
||||
"section": {
|
||||
"recent": "최근",
|
||||
"pages": "페이지",
|
||||
"cameras": "카메라",
|
||||
"cameraGroups": "카메라 그룹",
|
||||
"settings": "설정",
|
||||
"actions": "작업"
|
||||
},
|
||||
"camera": {
|
||||
"live": "라이브",
|
||||
"review": "리뷰"
|
||||
},
|
||||
"action": {
|
||||
"toggleTheme": "라이트 모드와 다크 모드를 전환합니다"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -121,15 +121,6 @@
|
||||
"partial": "{{total}}건 중 {{successful}}건의 내보내기를 시작했습니다. 실패 항목: {{failedItems}}",
|
||||
"failed": "{{total}}건의 내보내기 시작에 실패했습니다. 실패 항목: {{failedItems}}"
|
||||
}
|
||||
},
|
||||
"stream": {
|
||||
"label": "품질",
|
||||
"auto": "자동",
|
||||
"main": "원본",
|
||||
"sub": "낮음",
|
||||
"autoDesc": "메인 스트림을 사용합니다. 메인 스트림이 사용불가능할 경우 저품질 서브스트림으로 돌아옵니다.",
|
||||
"mainDesc": "원본 품질의 메인스트림만 내보내기합니다. 메인스트림이 누락된 시간대는 제외됩니다.",
|
||||
"subDesc": "저품질의 서브스트림만 내보내기합니다. 서브스트림이 누락된 시간대는 제외됩니다."
|
||||
}
|
||||
},
|
||||
"streaming": {
|
||||
@@ -175,8 +166,7 @@
|
||||
"export": "내보내기",
|
||||
"markAsReviewed": "검토 완료로 표시",
|
||||
"markAsUnreviewed": "미검토 상태로 표시",
|
||||
"deleteNow": "지금 삭제",
|
||||
"generateDescription": "설명 생성"
|
||||
"deleteNow": "지금 삭제"
|
||||
},
|
||||
"shareTimestamp": {
|
||||
"label": "타임스탬프 공유",
|
||||
@@ -185,12 +175,6 @@
|
||||
"custom": "사용자 지정 타임스탬프",
|
||||
"button": "타임스탬프 URL 공유",
|
||||
"shareTitle": "Frigate 다시보기 타임스탬프: {{camera}}"
|
||||
},
|
||||
"genaiDescription": {
|
||||
"toast": {
|
||||
"success": "이 검토 항목에 대한 생성형 AI 설명 생성을 요청했습니다.",
|
||||
"error": "설명 생성 요청 실패: {{error}}"
|
||||
}
|
||||
}
|
||||
},
|
||||
"imagePicker": {
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
"short": "대역폭",
|
||||
"title": "대역폭:"
|
||||
},
|
||||
"latency": {
|
||||
"short": {
|
||||
"title": "지연",
|
||||
"value": "{{seconds}}초"
|
||||
},
|
||||
"title": "지연 시간:",
|
||||
"value": "{{seconds}}초"
|
||||
},
|
||||
"streamType": {
|
||||
"short": "종류",
|
||||
"title": "스트림 종류:"
|
||||
@@ -37,23 +45,8 @@
|
||||
"submittedFrigatePlus": "Frigate+에 프레임을 성공적으로 제출했습니다"
|
||||
},
|
||||
"error": {
|
||||
"submitFrigatePlusFailed": "Frigate+에 프레임을 제출하지 못했습니다",
|
||||
"playRecordingsFailed": "녹화본 재생실패 (에러 {{code}}): {{message}}"
|
||||
"submitFrigatePlusFailed": "Frigate+에 프레임을 제출하지 못했습니다"
|
||||
}
|
||||
},
|
||||
"cameraOff": "카메라가 꺼져 있습니다",
|
||||
"quality": {
|
||||
"auto": "자동",
|
||||
"autoLow": "저화질 재생 (대역폭 제한)",
|
||||
"autoLowCodec": "저화질 재생 (브라우저에서 원본 형식을 지원하지 않음)",
|
||||
"autoLowSaveData": "저화질 재생 (데이터 절약)",
|
||||
"main": "원본",
|
||||
"sub": "저화질",
|
||||
"notSupportedBrowser": "이 브라우저에서는 지원되지 않음",
|
||||
"label": "화질",
|
||||
"noAudio": "오디오 없음",
|
||||
"audioRate": "{{rate}} kHz 오디오",
|
||||
"audioCodecRate": "{{codec}} {{rate}} kHz",
|
||||
"noRecordings": "이 시간 범위에 녹화본이 없습니다"
|
||||
}
|
||||
"cameraOff": "카메라가 꺼져 있습니다"
|
||||
}
|
||||
|
||||
@@ -46,10 +46,6 @@
|
||||
"num_threads": {
|
||||
"label": "감지 스레드 수",
|
||||
"description": "오디오 감지 처리에 사용할 스레드 수입니다."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "오디오 라벨 맵 사용자 지정",
|
||||
"description": "표준 오디오 라벨 맵에 병합할 재지정 또는 재매핑 항목입니다."
|
||||
}
|
||||
},
|
||||
"mqtt": {
|
||||
@@ -179,7 +175,7 @@
|
||||
}
|
||||
},
|
||||
"audio_transcription": {
|
||||
"label": "오디오 텍스트 변환",
|
||||
"label": "오디오 텍스트 변환 (STT)",
|
||||
"description": "이벤트 및 실시간 자막 처리에 사용되는 실시간 음성 전사 설정입니다.",
|
||||
"enabled": {
|
||||
"label": "텍스트 변환 활성화",
|
||||
@@ -203,15 +199,11 @@
|
||||
"order": {
|
||||
"label": "표시 순서",
|
||||
"description": "버드아이 레이아웃 내에서 카메라 배치 순서를 제어하는 숫자입니다."
|
||||
},
|
||||
"modes": {
|
||||
"label": "활동 유형",
|
||||
"description": "버드아이 화면에 카메라를 포함할 활동 유형입니다."
|
||||
}
|
||||
},
|
||||
"detect": {
|
||||
"label": "객체 감지",
|
||||
"description": "객체 감지를 실행하고 트래커를 초기화하는 데 사용되는 감지 역할 설정입니다.",
|
||||
"description": "객체 감지를 실행하고 트래커를 초기화하는 데 사용되는 detect 역할 설정입니다.",
|
||||
"enabled": {
|
||||
"label": "객체 감지 활성화",
|
||||
"description": "이 카메라의 객체 감지를 활성화하거나 비활성화합니다."
|
||||
@@ -267,10 +259,6 @@
|
||||
"annotation_offset": {
|
||||
"label": "어노테이션 오프셋",
|
||||
"description": "녹화 영상과 타임라인 바운딩 박스의 싱크를 맞추기 위해 감지 어노테이션을 전후로 이동할 밀리초(ms) 단위 시간입니다 (양수 또는 음수 가능)."
|
||||
},
|
||||
"scene": {
|
||||
"label": "감지 장면",
|
||||
"description": "이 카메라가 비추는 환경으로, 구성된 모델 중 어떤 모델을 실행할지 선택하는 데 사용됩니다. '전체'로 설정된 카메라는 장면이 '전체'로 구성된 모델을 실행합니다."
|
||||
}
|
||||
},
|
||||
"face_recognition": {
|
||||
@@ -314,10 +302,6 @@
|
||||
"record": {
|
||||
"label": "녹화(record) 출력 인수",
|
||||
"description": "record 역할 스트림에 적용할 기본 출력 인수입니다."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "서브 스트림 녹화 출력 인수",
|
||||
"description": "서브 녹화 스트림에 적용할 출력 인수입니다. 설정하지 않으면 기본 녹화 출력 인수가 사용됩니다."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
@@ -647,54 +631,6 @@
|
||||
"enabled_in_config": {
|
||||
"label": "초기 녹화 상태",
|
||||
"description": "초기 정적 구성에서 녹화가 활성화되어 있었는지 여부를 나타냅니다."
|
||||
},
|
||||
"sub": {
|
||||
"label": "서브 스트림 녹화",
|
||||
"description": "두 번째 저화질 스트림을 녹화하기 위한 설정입니다.",
|
||||
"enabled": {
|
||||
"label": "서브 스트림 녹화 사용",
|
||||
"description": "적응형 화질 재생 및 보관 기간 연장을 위해 두 번째 저화질 스트림 녹화를 활성화합니다."
|
||||
},
|
||||
"continuous": {
|
||||
"label": "서브 스트림 상시 녹화 보관 기간",
|
||||
"description": "추적된 객체나 움직임 발생 여부와 관계없이 서브 스트림 녹화본을 보관할 일수입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "녹화본을 보관할 일수입니다."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "서브 스트림 움직임 녹화 보관 기간",
|
||||
"description": "움직임 감지로 트리거된 서브 스트림 녹화본을 보관할 일수입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "녹화본을 보관할 일수입니다."
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"label": "서브 스트림 알림 녹화 보관 기간",
|
||||
"description": "알림 이벤트에 대한 서브 스트림 녹화본의 보관 설정입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "감지 이벤트 녹화본을 보관할 일수입니다."
|
||||
},
|
||||
"mode": {
|
||||
"label": "보관 모드",
|
||||
"description": "보관 모드: 전체(모든 구간 저장), 모션(움직임이 있는 구간 저장), 활성객체(활성 객체가 있는 구간 저장)."
|
||||
}
|
||||
},
|
||||
"detections": {
|
||||
"label": "서브 스트림 감지 녹화 보관 기간",
|
||||
"description": "감지 이벤트에 대한 서브 스트림 녹화본의 보관 설정입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "감지 이벤트 녹화본을 보관할 일수입니다."
|
||||
},
|
||||
"mode": {
|
||||
"label": "보관 모드",
|
||||
"description": "보관 모드: 전체(모든 구간 저장), 모션(움직임이 있는 구간 저장), 활성객체(활성 객체가 있는 구간 저장)."
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"review": {
|
||||
@@ -786,10 +722,6 @@
|
||||
"activity_context_prompt": {
|
||||
"label": "활동 맥락 프롬프트",
|
||||
"description": "GenAI 요약에 맥락을 제공하기 위해 어떤 활동이 의심스럽거나 정상적인지 설명하는 커스텀 프롬프트입니다."
|
||||
},
|
||||
"response_style": {
|
||||
"label": "응답 스타일",
|
||||
"description": "생성된 검토 설명의 작성 스타일 프리셋입니다. 프리셋은 사용자에게 표시되는 제목, 요약 및 장면 설명의 톤과 세부 수준을 조정하며, '초기값'으로 설정하면 내장 프롬프트를 그대로 유지합니다."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -57,11 +57,7 @@
|
||||
"label": "감지 스레드 수",
|
||||
"description": "오디오 감지 처리에 사용할 스레드 수입니다."
|
||||
},
|
||||
"description": "모든 카메라에 대한 오디오 기반 이벤트 감지 설정입니다. 카메라별로 재정의할 수 있습니다.",
|
||||
"labelmap": {
|
||||
"label": "오디오 라벨 맵 사용자 지정",
|
||||
"description": "표준 오디오 라벨 맵에 병합할 재지정 또는 재매핑 항목입니다."
|
||||
}
|
||||
"description": "모든 카메라에 대한 오디오 기반 이벤트 감지 설정입니다. 카메라별로 재정의할 수 있습니다."
|
||||
},
|
||||
"auth": {
|
||||
"label": "인증",
|
||||
@@ -224,7 +220,7 @@
|
||||
}
|
||||
},
|
||||
"audio_transcription": {
|
||||
"label": "오디오 텍스트 변환",
|
||||
"label": "오디오 텍스트 변환 (STT)",
|
||||
"description": "이벤트 및 실시간 자막 처리에 사용되는 실시간 음성 전사 설정입니다.",
|
||||
"live_enabled": {
|
||||
"label": "실시간 텍스트 변환",
|
||||
@@ -293,15 +289,11 @@
|
||||
"idle_heartbeat_fps": {
|
||||
"label": "유휴 하트비트 FPS",
|
||||
"description": "유휴 상태일 때 마지막으로 합성된 버드아이 프레임을 재전송할 초당 프레임 수입니다 (0은 비활성화)."
|
||||
},
|
||||
"modes": {
|
||||
"label": "활동 유형",
|
||||
"description": "버드아이 화면에 카메라를 포함할 활동 유형입니다."
|
||||
}
|
||||
},
|
||||
"detect": {
|
||||
"label": "객체 감지",
|
||||
"description": "객체 감지를 실행하고 트래커를 초기화하는 데 사용되는 감지 역할 설정입니다.",
|
||||
"description": "객체 감지를 실행하고 트래커를 초기화하는 데 사용되는 detect 역할 설정입니다.",
|
||||
"enabled": {
|
||||
"label": "객체 감지 활성화",
|
||||
"description": "모든 카메라의 객체 감지를 활성화하거나 비활성화합니다. 카메라별로 재정의할 수 있습니다."
|
||||
@@ -357,10 +349,6 @@
|
||||
"annotation_offset": {
|
||||
"label": "어노테이션 오프셋",
|
||||
"description": "녹화 영상과 타임라인 바운딩 박스의 싱크를 맞추기 위해 감지 어노테이션을 전후로 이동할 밀리초(ms) 단위 시간입니다 (양수 또는 음수 가능)."
|
||||
},
|
||||
"scene": {
|
||||
"label": "감지 장면",
|
||||
"description": "이 카메라가 비추는 환경으로, 구성된 모델 중 어떤 모델을 실행할지 선택하는 데 사용됩니다. '전체'로 설정된 카메라는 장면이 '전체'로 구성된 모델을 실행합니다."
|
||||
}
|
||||
},
|
||||
"face_recognition": {
|
||||
@@ -434,10 +422,6 @@
|
||||
"record": {
|
||||
"label": "녹화(record) 출력 인수",
|
||||
"description": "record 역할 스트림에 적용할 기본 출력 인수입니다."
|
||||
},
|
||||
"record_sub": {
|
||||
"label": "서브 스트림 녹화 출력 인수",
|
||||
"description": "서브 녹화 스트림에 적용할 출력 인수입니다. 설정하지 않으면 기본 녹화 출력 인수가 사용됩니다."
|
||||
}
|
||||
},
|
||||
"retry_interval": {
|
||||
@@ -850,55 +834,7 @@
|
||||
"label": "초기 녹화 상태",
|
||||
"description": "초기 정적 구성에서 녹화가 활성화되어 있었는지 여부를 나타냅니다."
|
||||
},
|
||||
"description": "카메라별로 재정의하지 않는 한 모든 카메라에 적용되는 녹화 및 보관 설정입니다.",
|
||||
"sub": {
|
||||
"label": "서브 스트림 녹화",
|
||||
"description": "두 번째 저화질 스트림을 녹화하기 위한 설정입니다.",
|
||||
"enabled": {
|
||||
"label": "서브 스트림 녹화 사용",
|
||||
"description": "적응형 화질 재생 및 보관 기간 연장을 위해 두 번째 저화질 스트림 녹화를 활성화합니다."
|
||||
},
|
||||
"continuous": {
|
||||
"label": "서브 스트림 상시 녹화 보관 기간",
|
||||
"description": "추적된 객체나 움직임 발생 여부와 관계없이 서브 스트림 녹화본을 보관할 일수입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "녹화본을 보관할 일수입니다."
|
||||
}
|
||||
},
|
||||
"motion": {
|
||||
"label": "서브 스트림 움직임 녹화 보관 기간",
|
||||
"description": "움직임 감지로 트리거된 서브 스트림 녹화본을 보관할 일수입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "녹화본을 보관할 일수입니다."
|
||||
}
|
||||
},
|
||||
"alerts": {
|
||||
"label": "서브 스트림 알림 녹화 보관 기간",
|
||||
"description": "알림 이벤트에 대한 서브 스트림 녹화본의 보관 설정입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "감지 이벤트 녹화본을 보관할 일수입니다."
|
||||
},
|
||||
"mode": {
|
||||
"label": "보관 모드",
|
||||
"description": "보관 모드: 전체(모든 구간 저장), 모션(움직임이 있는 구간 저장), 활성객체(활성 객체가 있는 구간 저장)."
|
||||
}
|
||||
},
|
||||
"detections": {
|
||||
"label": "서브 스트림 감지 녹화 보관 기간",
|
||||
"description": "감지 이벤트에 대한 서브 스트림 녹화본의 보관 설정입니다.",
|
||||
"days": {
|
||||
"label": "보관 일수",
|
||||
"description": "감지 이벤트 녹화본을 보관할 일수입니다."
|
||||
},
|
||||
"mode": {
|
||||
"label": "보관 모드",
|
||||
"description": "보관 모드: 전체(모든 구간 저장), 모션(움직임이 있는 구간 저장), 활성객체(활성 객체가 있는 구간 저장)."
|
||||
}
|
||||
}
|
||||
}
|
||||
"description": "카메라별로 재정의하지 않는 한 모든 카메라에 적용되는 녹화 및 보관 설정입니다."
|
||||
},
|
||||
"review": {
|
||||
"label": "다시보기",
|
||||
@@ -988,10 +924,6 @@
|
||||
"activity_context_prompt": {
|
||||
"label": "활동 맥락 프롬프트",
|
||||
"description": "GenAI 요약에 맥락을 제공하기 위해 어떤 활동이 의심스럽거나 정상적인지 설명하는 커스텀 프롬프트입니다."
|
||||
},
|
||||
"response_style": {
|
||||
"label": "응답 스타일",
|
||||
"description": "생성된 검토 설명의 작성 스타일 프리셋입니다. 프리셋은 사용자에게 표시되는 제목, 요약 및 장면 설명의 톤과 세부 수준을 조정하며, '초기값'으로 설정하면 내장 프롬프트를 그대로 유지합니다."
|
||||
}
|
||||
},
|
||||
"description": "UI 및 저장소에서 사용하는 알림, 감지 및 GenAI 요약을 제어하는 설정입니다."
|
||||
@@ -1241,7 +1173,7 @@
|
||||
},
|
||||
"default_role": {
|
||||
"label": "기본 역할",
|
||||
"description": "일치하는 역할 매핑이 없을 때 프록시 인증 사용자에게 할당할 기본 역할입니다. 매핑되지 않은 사용자의 접근을 차단하려면 '없음'으로 설정하세요."
|
||||
"description": "일치하는 역할 매핑이 없을 때 프록시 인증 사용자에게 할당할 기본 역할입니다."
|
||||
},
|
||||
"separator": {
|
||||
"label": "구분자 문자",
|
||||
@@ -1467,57 +1399,5 @@
|
||||
"label": "다시보기에 표시",
|
||||
"description": "다시보기 페이지(카메라 필터, 모션 검토 및 기록 뷰 포함)에서 이 카메라를 표시할지 여부를 전환합니다."
|
||||
}
|
||||
},
|
||||
"models": {
|
||||
"label": "감지 모델",
|
||||
"description": "객체 감지 모델과 각 모델이 실행되는 하드웨어입니다. 카메라는 자신의 detect.scene 값과 모델의 scene 값을 일치시켜 사용할 모델을 선택합니다.",
|
||||
"scene": {
|
||||
"label": "모델 장면",
|
||||
"description": "이 모델이 사용되는 카메라 환경입니다. 카메라는 detect.scene을 일치하는 값으로 설정하여 모델을 선택하며, 별도로 설정하지 않은 카메라는 모두 '전체'를 사용합니다."
|
||||
},
|
||||
"devices": {
|
||||
"label": "감지 하드웨어",
|
||||
"description": "이 모델이 실행되는 하드웨어로, '<detector>' 또는 '<detector>:<device>' 형식으로 지정합니다 (예: 'edgetpu:pci:0' 또는 'openvino:GPU'). 동일한 장치를 여러 번 나열하면 해당 장치에서 추론 프로세스를 추가로 실행합니다."
|
||||
},
|
||||
"path": {
|
||||
"label": "사용자 지정 객체 감지기 모델 경로",
|
||||
"description": "사용자 지정 감지 모델 파일의 경로입니다 (Frigate+ 모델의 경우 plus://<model_id>)."
|
||||
},
|
||||
"labelmap_path": {
|
||||
"label": "사용자 지정 객체 감지기 라벨 맵",
|
||||
"description": "감지기에 사용되는 숫자 클래스를 문자열 라벨로 매핑하는 라벨 맵 파일의 경로입니다."
|
||||
},
|
||||
"width": {
|
||||
"label": "객체 감지 모델 입력 너비",
|
||||
"description": "모델 입력 텐서의 너비(픽셀 단위)입니다."
|
||||
},
|
||||
"height": {
|
||||
"label": "객체 감지 모델 입력 높이",
|
||||
"description": "모델 입력 텐서의 높이(픽셀 단위)입니다."
|
||||
},
|
||||
"labelmap": {
|
||||
"label": "라벨 맵 사용자 지정",
|
||||
"description": "표준 라벨 맵에 병합할 재지정 또는 재매핑 항목입니다."
|
||||
},
|
||||
"attributes_map": {
|
||||
"label": "객체 라벨-속성 라벨 매핑 맵",
|
||||
"description": "메타데이터를 첨부하는 데 사용되는 객체 라벨과 속성 라벨 간의 매핑입니다 (예: '자동차' -> ['번호판'])."
|
||||
},
|
||||
"input_tensor": {
|
||||
"label": "모델 입력 텐서 형태",
|
||||
"description": "모델이 요구하는 텐서 형식: 'nhwc' 또는 'nchw'."
|
||||
},
|
||||
"input_pixel_format": {
|
||||
"label": "모델 입력 픽셀 색상 형식",
|
||||
"description": "모델이 요구하는 픽셀 색 공간: 'rgb', 'bgr' 또는 'yuv'."
|
||||
},
|
||||
"input_dtype": {
|
||||
"label": "모델 입력 D 타입",
|
||||
"description": "모델 입력 텐서의 데이터 타입입니다 (예: 'float32')."
|
||||
},
|
||||
"model_type": {
|
||||
"label": "객체 감지 모델 유형",
|
||||
"description": "일부 감지기에서 최적화를 위해 사용하는 감지기 모델 아키텍처 유형(ssd, yolox, yolonas, yolo-generic, rfdetr, dfine)입니다."
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,8 +31,5 @@
|
||||
},
|
||||
"detect": {
|
||||
"dimensionMustBeEven": "짝수여야 합니다."
|
||||
},
|
||||
"models": {
|
||||
"defaultRequired": "하나의 모델은 반드시 '모든 카메라' 장면을 사용해야 합니다. 그렇지 않으면 특정 장면을 선택하지 않은 카메라가 대체 사용할 모델이 없게 됩니다."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,12 +55,6 @@
|
||||
"auto_scroll": {
|
||||
"title": "자동 스크롤",
|
||||
"desc": "새 메시지가 도착하면 화면을 자동으로 아래로 이동합니다."
|
||||
},
|
||||
"always_allow": {
|
||||
"title": "항상 허용된 작업",
|
||||
"desc": "어시스턴트가 매번 확인하지 않고 바로 실행할 수 있는 작업입니다.",
|
||||
"none": "없음",
|
||||
"reset": "초기화"
|
||||
}
|
||||
},
|
||||
"stats": {
|
||||
@@ -74,15 +68,5 @@
|
||||
},
|
||||
"thinking": {
|
||||
"toggle": "생각 과정 전환"
|
||||
},
|
||||
"approval": {
|
||||
"title": "{{tool}} 작업을 승인하시겠습니까?",
|
||||
"desc": "이 작업은 Frigate의 설정을 변경합니다. 승인하기 전에 세부 정보를 검토하세요.",
|
||||
"approve": "승인",
|
||||
"always_allow": "항상 허용",
|
||||
"reject": "거부",
|
||||
"approved": "승인됨",
|
||||
"rejected": "거부됨",
|
||||
"placeholder": "계속하려면 대기 중인 작업을 승인하거나 거부하세요"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,6 +91,5 @@
|
||||
"crop": "필터 영역으로 확대",
|
||||
"cropAria": "미리보기를 필터 영역으로 자르기 전환",
|
||||
"cropDesc": "전체 화면 대신 선택한 필터 영역으로 미리보기를 확대합니다."
|
||||
},
|
||||
"subOnlyQuality": "이 시간 범위에는 저화질 녹화본만 사용할 수 있습니다"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -65,8 +65,7 @@
|
||||
"copying": "복사 중",
|
||||
"encoding": "인코딩 중",
|
||||
"encodingRetry": "인코딩 재시도 중",
|
||||
"finalizing": "마무리 중",
|
||||
"merging": "병합 중"
|
||||
"finalizing": "마무리 중"
|
||||
},
|
||||
"caseView": {
|
||||
"noDescription": "설명 없음",
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user