Merge branch 'dev' into dev-zone-friendly-name

This commit is contained in:
GuoQing Liu 2025-10-24 22:16:14 +08:00 committed by GitHub
commit 47577f6962
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
240 changed files with 10861 additions and 1109 deletions

View File

@ -0,0 +1,6 @@
---
globs: ["**/*.ts", "**/*.tsx"]
alwaysApply: false
---
Never write strings in the frontend directly, always write to and reference the relevant translations file.

View File

@ -73,6 +73,8 @@ http {
vod_manifest_segment_durations_mode accurate; vod_manifest_segment_durations_mode accurate;
vod_ignore_edit_list on; vod_ignore_edit_list on;
vod_segment_duration 10000; vod_segment_duration 10000;
# MPEG-TS settings (not used when fMP4 is enabled, kept for reference)
vod_hls_mpegts_align_frames off; vod_hls_mpegts_align_frames off;
vod_hls_mpegts_interleave_frames on; vod_hls_mpegts_interleave_frames on;
@ -105,6 +107,10 @@ http {
aio threads; aio threads;
vod hls; vod hls;
# Use fMP4 (fragmented MP4) instead of MPEG-TS for better performance
# Smaller segments, faster generation, better browser compatibility
vod_hls_container_format fmp4;
secure_token $args; secure_token $args;
secure_token_types application/vnd.apple.mpegurl; secure_token_types application/vnd.apple.mpegurl;
@ -274,6 +280,18 @@ http {
include proxy.conf; include proxy.conf;
} }
# Allow unauthenticated access to the first_time_login endpoint
# so the login page can load help text before authentication.
location /api/auth/first_time_login {
auth_request off;
limit_except GET {
deny all;
}
rewrite ^/api(/.*)$ $1 break;
proxy_pass http://frigate_api;
include proxy.conf;
}
location /api/stats { location /api/stats {
include auth_request.conf; include auth_request.conf;
access_log off; access_log off;

View File

@ -12,7 +12,18 @@ Object classification models are lightweight and run very fast on CPU. Inference
Training the model does briefly use a high amount of system resources for about 13 minutes per training run. On lower-power devices, training may take longer. Training the model does briefly use a high amount of system resources for about 13 minutes per training run. On lower-power devices, training may take longer.
When running the `-tensorrt` image, Nvidia GPUs will automatically be used to accelerate training. When running the `-tensorrt` image, Nvidia GPUs will automatically be used to accelerate training.
### Sub label vs Attribute ## Classes
Classes are the categories your model will learn to distinguish between. Each class represents a distinct visual category that the model will predict.
For object classification:
- Define classes that represent different types or attributes of the detected object
- Examples: For `person` objects, classes might be `delivery_person`, `resident`, `stranger`
- Include a `none` class for objects that don't fit any specific category
- Keep classes visually distinct to improve accuracy
### Classification Type
- **Sub label**: - **Sub label**:
@ -67,7 +78,7 @@ When choosing which objects to classify, start with a small number of visually d
### Improving the Model ### Improving the Model
- **Problem framing**: Keep classes visually distinct and relevant to the chosen object types. - **Problem framing**: Keep classes visually distinct and relevant to the chosen object types.
- **Data collection**: Use the models Train tab to gather balanced examples across times of day, weather, and distances. - **Data collection**: Use the models Recent Classification tab to gather balanced examples across times of day, weather, and distances.
- **Preprocessing**: Ensure examples reflect object crops similar to Frigates boxes; keep the subject centered. - **Preprocessing**: Ensure examples reflect object crops similar to Frigates boxes; keep the subject centered.
- **Labels**: Keep label names short and consistent; include a `none` class if you plan to ignore uncertain predictions for sub labels. - **Labels**: Keep label names short and consistent; include a `none` class if you plan to ignore uncertain predictions for sub labels.
- **Threshold**: Tune `threshold` per model to reduce false assignments. Start at `0.8` and adjust based on validation. - **Threshold**: Tune `threshold` per model to reduce false assignments. Start at `0.8` and adjust based on validation.

View File

@ -12,6 +12,17 @@ State classification models are lightweight and run very fast on CPU. Inference
Training the model does briefly use a high amount of system resources for about 13 minutes per training run. On lower-power devices, training may take longer. Training the model does briefly use a high amount of system resources for about 13 minutes per training run. On lower-power devices, training may take longer.
When running the `-tensorrt` image, Nvidia GPUs will automatically be used to accelerate training. When running the `-tensorrt` image, Nvidia GPUs will automatically be used to accelerate training.
## Classes
Classes are the different states an area on your camera can be in. Each class represents a distinct visual state that the model will learn to recognize.
For state classification:
- Define classes that represent mutually exclusive states
- Examples: `open` and `closed` for a garage door, `on` and `off` for lights
- Use at least 2 classes (typically binary states work best)
- Keep class names clear and descriptive
## Example use cases ## Example use cases
- **Door state**: Detect if a garage or front door is open vs closed. - **Door state**: Detect if a garage or front door is open vs closed.
@ -49,4 +60,4 @@ When choosing a portion of the camera frame for state classification, it is impo
### Improving the Model ### Improving the Model
- **Problem framing**: Keep classes visually distinct and state-focused (e.g., `open`, `closed`, `unknown`). Avoid combining object identity with state in a single model unless necessary. - **Problem framing**: Keep classes visually distinct and state-focused (e.g., `open`, `closed`, `unknown`). Avoid combining object identity with state in a single model unless necessary.
- **Data collection**: Use the models Train tab to gather balanced examples across times of day and weather. - **Data collection**: Use the models Recent Classifications tab to gather balanced examples across times of day and weather.

View File

@ -70,7 +70,7 @@ Fine-tune face recognition with these optional parameters at the global level of
- `min_faces`: Min face recognitions for the sub label to be applied to the person object. - `min_faces`: Min face recognitions for the sub label to be applied to the person object.
- Default: `1` - Default: `1`
- `save_attempts`: Number of images of recognized faces to save for training. - `save_attempts`: Number of images of recognized faces to save for training.
- Default: `100`. - Default: `200`.
- `blur_confidence_filter`: Enables a filter that calculates how blurry the face is and adjusts the confidence based on this. - `blur_confidence_filter`: Enables a filter that calculates how blurry the face is and adjusts the confidence based on this.
- Default: `True`. - Default: `True`.
- `device`: Target a specific device to run the face recognition model on (multi-GPU installation). - `device`: Target a specific device to run the face recognition model on (multi-GPU installation).
@ -114,9 +114,9 @@ When choosing images to include in the face training set it is recommended to al
::: :::
### Understanding the Train Tab ### Understanding the Recent Recognitions Tab
The Train tab in the face library displays recent face recognition attempts. Detected face images are grouped according to the person they were identified as potentially matching. The Recent Recognitions tab in the face library displays recent face recognition attempts. Detected face images are grouped according to the person they were identified as potentially matching.
Each face image is labeled with a name (or `Unknown`) along with the confidence score of the recognition attempt. While each image can be used to train the system for a specific person, not all images are suitable for training. Each face image is labeled with a name (or `Unknown`) along with the confidence score of the recognition attempt. While each image can be used to train the system for a specific person, not all images are suitable for training.
@ -140,7 +140,7 @@ Once front-facing images are performing well, start choosing slightly off-angle
Start with the [Usage](#usage) section and re-read the [Model Requirements](#model-requirements) above. Start with the [Usage](#usage) section and re-read the [Model Requirements](#model-requirements) above.
1. Ensure `person` is being _detected_. A `person` will automatically be scanned by Frigate for a face. Any detected faces will appear in the Train tab in the Frigate UI's Face Library. 1. Ensure `person` is being _detected_. A `person` will automatically be scanned by Frigate for a face. Any detected faces will appear in the Recent Recognitions tab in the Frigate UI's Face Library.
If you are using a Frigate+ or `face` detecting model: If you are using a Frigate+ or `face` detecting model:
@ -186,7 +186,7 @@ Avoid training on images that already score highly, as this can lead to over-fit
No, face recognition does not support negative training (i.e., explicitly telling it who someone is _not_). Instead, the best approach is to improve the training data by using a more diverse and representative set of images for each person. No, face recognition does not support negative training (i.e., explicitly telling it who someone is _not_). Instead, the best approach is to improve the training data by using a more diverse and representative set of images for each person.
For more guidance, refer to the section above on improving recognition accuracy. For more guidance, refer to the section above on improving recognition accuracy.
### I see scores above the threshold in the train tab, but a sub label wasn't assigned? ### I see scores above the threshold in the Recent Recognitions tab, but a sub label wasn't assigned?
The Frigate considers the recognition scores across all recognition attempts for each person object. The scores are continually weighted based on the area of the face, and a sub label will only be assigned to person if a person is confidently recognized consistently. This avoids cases where a single high confidence recognition would throw off the results. The Frigate considers the recognition scores across all recognition attempts for each person object. The scores are continually weighted based on the area of the face, and a sub label will only be assigned to person if a person is confidently recognized consistently. This avoids cases where a single high confidence recognition would throw off the results.

View File

@ -630,7 +630,7 @@ face_recognition:
# Optional: Min face recognitions for the sub label to be applied to the person object (default: shown below) # Optional: Min face recognitions for the sub label to be applied to the person object (default: shown below)
min_faces: 1 min_faces: 1
# Optional: Number of images of recognized faces to save for training (default: shown below) # Optional: Number of images of recognized faces to save for training (default: shown below)
save_attempts: 100 save_attempts: 200
# Optional: Apply a blur quality filter to adjust confidence based on the blur level of the image (default: shown below) # Optional: Apply a blur quality filter to adjust confidence based on the blur level of the image (default: shown below)
blur_confidence_filter: True blur_confidence_filter: True
# Optional: Set the model size used face recognition. (default: shown below) # Optional: Set the model size used face recognition. (default: shown below)
@ -671,20 +671,18 @@ lpr:
# Optional: List of regex replacement rules to normalize detected plates (default: shown below) # Optional: List of regex replacement rules to normalize detected plates (default: shown below)
replace_rules: {} replace_rules: {}
# Optional: Configuration for AI generated tracked object descriptions # Optional: Configuration for AI / LLM provider
# WARNING: Depending on the provider, this will send thumbnails over the internet # WARNING: Depending on the provider, this will send thumbnails over the internet
# to Google or OpenAI's LLMs to generate descriptions. It can be overridden at # to Google or OpenAI's LLMs to generate descriptions. GenAI features can be configured at
# the camera level (enabled: False) to enhance privacy for indoor cameras. # the camera level to enhance privacy for indoor cameras.
genai: genai:
# Optional: Enable AI description generation (default: shown below) # Required: Provider must be one of ollama, gemini, or openai
enabled: False
# Required if enabled: Provider must be one of ollama, gemini, or openai
provider: ollama provider: ollama
# Required if provider is ollama. May also be used for an OpenAI API compatible backend with the openai provider. # Required if provider is ollama. May also be used for an OpenAI API compatible backend with the openai provider.
base_url: http://localhost::11434 base_url: http://localhost::11434
# Required if gemini or openai # Required if gemini or openai
api_key: "{FRIGATE_GENAI_API_KEY}" api_key: "{FRIGATE_GENAI_API_KEY}"
# Required if enabled: The model to use with the provider. # Required: The model to use with the provider.
model: gemini-1.5-flash model: gemini-1.5-flash
# Optional additional args to pass to the GenAI Provider (default: None) # Optional additional args to pass to the GenAI Provider (default: None)
provider_options: provider_options:

View File

@ -387,20 +387,28 @@ def config_set(request: Request, body: AppConfigSetBody):
old_config: FrigateConfig = request.app.frigate_config old_config: FrigateConfig = request.app.frigate_config
request.app.frigate_config = config request.app.frigate_config = config
if body.update_topic and body.update_topic.startswith("config/cameras/"): if body.update_topic:
_, _, camera, field = body.update_topic.split("/") if body.update_topic.startswith("config/cameras/"):
_, _, camera, field = body.update_topic.split("/")
if field == "add": if field == "add":
settings = config.cameras[camera] settings = config.cameras[camera]
elif field == "remove": elif field == "remove":
settings = old_config.cameras[camera] settings = old_config.cameras[camera]
else:
settings = config.get_nested_object(body.update_topic)
request.app.config_publisher.publish_update(
CameraConfigUpdateTopic(CameraConfigUpdateEnum[field], camera),
settings,
)
else: else:
# Handle nested config updates (e.g., config/classification/custom/{name})
settings = config.get_nested_object(body.update_topic) settings = config.get_nested_object(body.update_topic)
if settings:
request.app.config_publisher.publish_update( request.app.config_publisher.publisher.publish(
CameraConfigUpdateTopic(CameraConfigUpdateEnum[field], camera), body.update_topic, settings
settings, )
)
return JSONResponse( return JSONResponse(
content=( content=(

View File

@ -35,6 +35,23 @@ logger = logging.getLogger(__name__)
router = APIRouter(tags=[Tags.auth]) router = APIRouter(tags=[Tags.auth])
@router.get("/auth/first_time_login")
def first_time_login(request: Request):
"""Return whether the admin first-time login help flag is set in config.
This endpoint is intentionally unauthenticated so the login page can
query it before a user is authenticated.
"""
auth_config = request.app.frigate_config.auth
return JSONResponse(
content={
"admin_first_time_login": auth_config.admin_first_time_login
or auth_config.reset_admin_password
}
)
class RateLimiter: class RateLimiter:
_limit = "" _limit = ""
@ -515,6 +532,11 @@ def login(request: Request, body: AppPostLoginBody):
set_jwt_cookie( set_jwt_cookie(
response, JWT_COOKIE_NAME, encoded_jwt, expiration, JWT_COOKIE_SECURE response, JWT_COOKIE_NAME, encoded_jwt, expiration, JWT_COOKIE_SECURE
) )
# Clear admin_first_time_login flag after successful admin login so the
# UI stops showing the first-time login documentation link.
if role == "admin":
request.app.frigate_config.auth.admin_first_time_login = False
return response return response
return JSONResponse(content={"message": "Login failed"}, status_code=401) return JSONResponse(content={"message": "Login failed"}, status_code=401)

View File

@ -199,19 +199,30 @@ def ffprobe(request: Request, paths: str = "", detailed: bool = False):
request.app.frigate_config.ffmpeg, path.strip(), detailed=detailed request.app.frigate_config.ffmpeg, path.strip(), detailed=detailed
) )
result = { if ffprobe.returncode != 0:
"return_code": ffprobe.returncode, try:
"stderr": ( stderr_decoded = ffprobe.stderr.decode("utf-8")
ffprobe.stderr.decode("unicode_escape").strip() except UnicodeDecodeError:
if ffprobe.returncode != 0 try:
else "" stderr_decoded = ffprobe.stderr.decode("unicode_escape")
), except Exception:
"stdout": ( stderr_decoded = str(ffprobe.stderr)
json.loads(ffprobe.stdout.decode("unicode_escape").strip())
if ffprobe.returncode == 0 stderr_lines = [
else "" line.strip() for line in stderr_decoded.split("\n") if line.strip()
), ]
}
result = {
"return_code": ffprobe.returncode,
"stderr": stderr_lines,
"stdout": "",
}
else:
result = {
"return_code": ffprobe.returncode,
"stderr": [],
"stdout": json.loads(ffprobe.stdout.decode("unicode_escape").strip()),
}
# Add detailed metadata if requested and probe was successful # Add detailed metadata if requested and probe was successful
if detailed and ffprobe.returncode == 0 and result["stdout"]: if detailed and ffprobe.returncode == 0 and result["stdout"]:

View File

@ -3,7 +3,9 @@
import datetime import datetime
import logging import logging
import os import os
import random
import shutil import shutil
import string
from typing import Any from typing import Any
import cv2 import cv2
@ -17,6 +19,8 @@ from frigate.api.auth import require_role
from frigate.api.defs.request.classification_body import ( from frigate.api.defs.request.classification_body import (
AudioTranscriptionBody, AudioTranscriptionBody,
DeleteFaceImagesBody, DeleteFaceImagesBody,
GenerateObjectExamplesBody,
GenerateStateExamplesBody,
RenameFaceBody, RenameFaceBody,
) )
from frigate.api.defs.response.classification_response import ( from frigate.api.defs.response.classification_response import (
@ -30,6 +34,10 @@ from frigate.config.camera import DetectConfig
from frigate.const import CLIPS_DIR, FACE_DIR from frigate.const import CLIPS_DIR, FACE_DIR
from frigate.embeddings import EmbeddingsContext from frigate.embeddings import EmbeddingsContext
from frigate.models import Event from frigate.models import Event
from frigate.util.classification import (
collect_object_classification_examples,
collect_state_classification_examples,
)
from frigate.util.path import get_event_snapshot from frigate.util.path import get_event_snapshot
logger = logging.getLogger(__name__) logger = logging.getLogger(__name__)
@ -159,8 +167,7 @@ def train_face(request: Request, name: str, body: dict = None):
new_name = f"{sanitized_name}-{datetime.datetime.now().timestamp()}.webp" new_name = f"{sanitized_name}-{datetime.datetime.now().timestamp()}.webp"
new_file_folder = os.path.join(FACE_DIR, f"{sanitized_name}") new_file_folder = os.path.join(FACE_DIR, f"{sanitized_name}")
if not os.path.exists(new_file_folder): os.makedirs(new_file_folder, exist_ok=True)
os.mkdir(new_file_folder)
if training_file_name: if training_file_name:
shutil.move(training_file, os.path.join(new_file_folder, new_name)) shutil.move(training_file, os.path.join(new_file_folder, new_name))
@ -701,13 +708,14 @@ def categorize_classification_image(request: Request, name: str, body: dict = No
status_code=404, status_code=404,
) )
new_name = f"{category}-{datetime.datetime.now().timestamp()}.png" random_id = "".join(random.choices(string.ascii_lowercase + string.digits, k=6))
timestamp = datetime.datetime.now().timestamp()
new_name = f"{category}-{timestamp}-{random_id}.png"
new_file_folder = os.path.join( new_file_folder = os.path.join(
CLIPS_DIR, sanitize_filename(name), "dataset", category CLIPS_DIR, sanitize_filename(name), "dataset", category
) )
if not os.path.exists(new_file_folder): os.makedirs(new_file_folder, exist_ok=True)
os.mkdir(new_file_folder)
# use opencv because webp images can not be used to train # use opencv because webp images can not be used to train
img = cv2.imread(training_file) img = cv2.imread(training_file)
@ -756,3 +764,43 @@ def delete_classification_train_images(request: Request, name: str, body: dict =
content=({"success": True, "message": "Successfully deleted faces."}), content=({"success": True, "message": "Successfully deleted faces."}),
status_code=200, status_code=200,
) )
@router.post(
"/classification/generate_examples/state",
response_model=GenericResponse,
dependencies=[Depends(require_role(["admin"]))],
summary="Generate state classification examples",
)
async def generate_state_examples(request: Request, body: GenerateStateExamplesBody):
"""Generate examples for state classification."""
model_name = sanitize_filename(body.model_name)
cameras_normalized = {
camera_name: tuple(crop)
for camera_name, crop in body.cameras.items()
if camera_name in request.app.frigate_config.cameras
}
collect_state_classification_examples(model_name, cameras_normalized)
return JSONResponse(
content={"success": True, "message": "Example generation completed"},
status_code=200,
)
@router.post(
"/classification/generate_examples/object",
response_model=GenericResponse,
dependencies=[Depends(require_role(["admin"]))],
summary="Generate object classification examples",
)
async def generate_object_examples(request: Request, body: GenerateObjectExamplesBody):
"""Generate examples for object classification."""
model_name = sanitize_filename(body.model_name)
collect_object_classification_examples(model_name, body.label)
return JSONResponse(
content={"success": True, "message": "Example generation completed"},
status_code=200,
)

View File

@ -1,17 +1,31 @@
from typing import List from typing import Dict, List, Tuple
from pydantic import BaseModel, Field from pydantic import BaseModel, Field
class RenameFaceBody(BaseModel): class RenameFaceBody(BaseModel):
new_name: str new_name: str = Field(description="New name for the face")
class AudioTranscriptionBody(BaseModel): class AudioTranscriptionBody(BaseModel):
event_id: str event_id: str = Field(description="ID of the event to transcribe audio for")
class DeleteFaceImagesBody(BaseModel): class DeleteFaceImagesBody(BaseModel):
ids: List[str] = Field( ids: List[str] = Field(
description="List of image filenames to delete from the face folder" description="List of image filenames to delete from the face folder"
) )
class GenerateStateExamplesBody(BaseModel):
model_name: str = Field(description="Name of the classification model")
cameras: Dict[str, Tuple[float, float, float, float]] = Field(
description="Dictionary mapping camera names to normalized crop coordinates in [x1, y1, x2, y2] format (values 0-1)"
)
class GenerateObjectExamplesBody(BaseModel):
model_name: str = Field(description="Name of the classification model")
label: str = Field(
description="Object label to collect examples for (e.g., 'person', 'car')"
)

View File

@ -488,6 +488,8 @@ class FrigateApp:
} }
).execute() ).execute()
self.config.auth.admin_first_time_login = True
logger.info("********************************************************") logger.info("********************************************************")
logger.info("********************************************************") logger.info("********************************************************")
logger.info("*** Auth is enabled, but no users exist. ***") logger.info("*** Auth is enabled, but no users exist. ***")

View File

@ -38,6 +38,13 @@ class AuthConfig(FrigateBaseModel):
default_factory=dict, default_factory=dict,
title="Role to camera mappings. Empty list grants access to all cameras.", title="Role to camera mappings. Empty list grants access to all cameras.",
) )
admin_first_time_login: Optional[bool] = Field(
default=False,
title="Internal field to expose first-time admin login flag to the UI",
description=(
"When true the UI may show a help link on the login page informing users how to sign in after an admin password reset. "
),
)
@field_validator("roles") @field_validator("roles")
@classmethod @classmethod

View File

@ -69,7 +69,7 @@ class BirdClassificationConfig(FrigateBaseModel):
class CustomClassificationStateCameraConfig(FrigateBaseModel): class CustomClassificationStateCameraConfig(FrigateBaseModel):
crop: list[int, int, int, int] = Field( crop: list[float, float, float, float] = Field(
title="Crop of image frame on this camera to run classification on." title="Crop of image frame on this camera to run classification on."
) )
@ -197,7 +197,9 @@ class FaceRecognitionConfig(FrigateBaseModel):
title="Min face recognitions for the sub label to be applied to the person object.", title="Min face recognitions for the sub label to be applied to the person object.",
) )
save_attempts: int = Field( save_attempts: int = Field(
default=100, ge=0, title="Number of face attempts to save in the train tab." default=200,
ge=0,
title="Number of face attempts to save in the recent recognitions tab.",
) )
blur_confidence_filter: bool = Field( blur_confidence_filter: bool = Field(
default=True, title="Apply blur quality filter to face confidence." default=True, title="Apply blur quality filter to face confidence."

View File

@ -53,9 +53,17 @@ class CustomStateClassificationProcessor(RealTimeProcessorApi):
self.tensor_output_details: dict[str, Any] | None = None self.tensor_output_details: dict[str, Any] | None = None
self.labelmap: dict[int, str] = {} self.labelmap: dict[int, str] = {}
self.classifications_per_second = EventsPerSecond() self.classifications_per_second = EventsPerSecond()
self.inference_speed = InferenceSpeed(
self.metrics.classification_speeds[self.model_config.name] if (
) self.metrics
and self.model_config.name in self.metrics.classification_speeds
):
self.inference_speed = InferenceSpeed(
self.metrics.classification_speeds[self.model_config.name]
)
else:
self.inference_speed = None
self.last_run = datetime.datetime.now().timestamp() self.last_run = datetime.datetime.now().timestamp()
self.__build_detector() self.__build_detector()
@ -83,12 +91,14 @@ class CustomStateClassificationProcessor(RealTimeProcessorApi):
def __update_metrics(self, duration: float) -> None: def __update_metrics(self, duration: float) -> None:
self.classifications_per_second.update() self.classifications_per_second.update()
self.inference_speed.update(duration) if self.inference_speed:
self.inference_speed.update(duration)
def process_frame(self, frame_data: dict[str, Any], frame: np.ndarray): def process_frame(self, frame_data: dict[str, Any], frame: np.ndarray):
self.metrics.classification_cps[ if self.metrics and self.model_config.name in self.metrics.classification_cps:
self.model_config.name self.metrics.classification_cps[
].value = self.classifications_per_second.eps() self.model_config.name
].value = self.classifications_per_second.eps()
camera = frame_data.get("camera") camera = frame_data.get("camera")
if camera not in self.model_config.state_config.cameras: if camera not in self.model_config.state_config.cameras:
@ -96,10 +106,10 @@ class CustomStateClassificationProcessor(RealTimeProcessorApi):
camera_config = self.model_config.state_config.cameras[camera] camera_config = self.model_config.state_config.cameras[camera]
crop = [ crop = [
camera_config.crop[0], camera_config.crop[0] * self.config.cameras[camera].detect.width,
camera_config.crop[1], camera_config.crop[1] * self.config.cameras[camera].detect.height,
camera_config.crop[2], camera_config.crop[2] * self.config.cameras[camera].detect.width,
camera_config.crop[3], camera_config.crop[3] * self.config.cameras[camera].detect.height,
] ]
should_run = False should_run = False
@ -223,9 +233,17 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
self.detected_objects: dict[str, float] = {} self.detected_objects: dict[str, float] = {}
self.labelmap: dict[int, str] = {} self.labelmap: dict[int, str] = {}
self.classifications_per_second = EventsPerSecond() self.classifications_per_second = EventsPerSecond()
self.inference_speed = InferenceSpeed(
self.metrics.classification_speeds[self.model_config.name] if (
) self.metrics
and self.model_config.name in self.metrics.classification_speeds
):
self.inference_speed = InferenceSpeed(
self.metrics.classification_speeds[self.model_config.name]
)
else:
self.inference_speed = None
self.__build_detector() self.__build_detector()
@redirect_output_to_logger(logger, logging.DEBUG) @redirect_output_to_logger(logger, logging.DEBUG)
@ -251,12 +269,14 @@ class CustomObjectClassificationProcessor(RealTimeProcessorApi):
def __update_metrics(self, duration: float) -> None: def __update_metrics(self, duration: float) -> None:
self.classifications_per_second.update() self.classifications_per_second.update()
self.inference_speed.update(duration) if self.inference_speed:
self.inference_speed.update(duration)
def process_frame(self, obj_data, frame): def process_frame(self, obj_data, frame):
self.metrics.classification_cps[ if self.metrics and self.model_config.name in self.metrics.classification_cps:
self.model_config.name self.metrics.classification_cps[
].value = self.classifications_per_second.eps() self.model_config.name
].value = self.classifications_per_second.eps()
if obj_data["false_positive"]: if obj_data["false_positive"]:
return return

View File

@ -9,6 +9,7 @@ from typing import Any
from peewee import DoesNotExist from peewee import DoesNotExist
from frigate.comms.config_updater import ConfigSubscriber
from frigate.comms.detections_updater import DetectionSubscriber, DetectionTypeEnum from frigate.comms.detections_updater import DetectionSubscriber, DetectionTypeEnum
from frigate.comms.embeddings_updater import ( from frigate.comms.embeddings_updater import (
EmbeddingsRequestEnum, EmbeddingsRequestEnum,
@ -95,6 +96,9 @@ class EmbeddingMaintainer(threading.Thread):
CameraConfigUpdateEnum.semantic_search, CameraConfigUpdateEnum.semantic_search,
], ],
) )
self.classification_config_subscriber = ConfigSubscriber(
"config/classification/custom/"
)
# Configure Frigate DB # Configure Frigate DB
db = SqliteVecQueueDatabase( db = SqliteVecQueueDatabase(
@ -255,6 +259,7 @@ class EmbeddingMaintainer(threading.Thread):
"""Maintain a SQLite-vec database for semantic search.""" """Maintain a SQLite-vec database for semantic search."""
while not self.stop_event.is_set(): while not self.stop_event.is_set():
self.config_updater.check_for_updates() self.config_updater.check_for_updates()
self._check_classification_config_updates()
self._process_requests() self._process_requests()
self._process_updates() self._process_updates()
self._process_recordings_updates() self._process_recordings_updates()
@ -265,6 +270,7 @@ class EmbeddingMaintainer(threading.Thread):
self._process_event_metadata() self._process_event_metadata()
self.config_updater.stop() self.config_updater.stop()
self.classification_config_subscriber.stop()
self.event_subscriber.stop() self.event_subscriber.stop()
self.event_end_subscriber.stop() self.event_end_subscriber.stop()
self.recordings_subscriber.stop() self.recordings_subscriber.stop()
@ -275,6 +281,46 @@ class EmbeddingMaintainer(threading.Thread):
self.requestor.stop() self.requestor.stop()
logger.info("Exiting embeddings maintenance...") logger.info("Exiting embeddings maintenance...")
def _check_classification_config_updates(self) -> None:
"""Check for classification config updates and add new processors."""
topic, model_config = self.classification_config_subscriber.check_for_update()
if topic and model_config:
model_name = topic.split("/")[-1]
self.config.classification.custom[model_name] = model_config
# Check if processor already exists
for processor in self.realtime_processors:
if isinstance(
processor,
(
CustomStateClassificationProcessor,
CustomObjectClassificationProcessor,
),
):
if processor.model_config.name == model_name:
logger.debug(
f"Classification processor for model {model_name} already exists, skipping"
)
return
if model_config.state_config is not None:
processor = CustomStateClassificationProcessor(
self.config, model_config, self.requestor, self.metrics
)
else:
processor = CustomObjectClassificationProcessor(
self.config,
model_config,
self.event_metadata_publisher,
self.metrics,
)
self.realtime_processors.append(processor)
logger.info(
f"Added classification processor for model: {model_name} (type: {type(processor).__name__})"
)
def _process_requests(self) -> None: def _process_requests(self) -> None:
"""Process embeddings requests""" """Process embeddings requests"""

View File

@ -150,10 +150,10 @@ PRESETS_HW_ACCEL_SCALE["preset-rk-h265"] = PRESETS_HW_ACCEL_SCALE[FFMPEG_HWACCEL
PRESETS_HW_ACCEL_ENCODE_BIRDSEYE = { PRESETS_HW_ACCEL_ENCODE_BIRDSEYE = {
"preset-rpi-64-h264": "{0} -hide_banner {1} -c:v h264_v4l2m2m {2}", "preset-rpi-64-h264": "{0} -hide_banner {1} -c:v h264_v4l2m2m {2}",
"preset-rpi-64-h265": "{0} -hide_banner {1} -c:v hevc_v4l2m2m {2}", "preset-rpi-64-h265": "{0} -hide_banner {1} -c:v hevc_v4l2m2m {2}",
FFMPEG_HWACCEL_VAAPI: "{0} -hide_banner -hwaccel vaapi -hwaccel_output_format vaapi {3} {1} -c:v h264_vaapi -g 50 -bf 0 -profile:v high -level:v 4.1 -sei:v 0 -an -vf format=vaapi|nv12,hwupload {2}", FFMPEG_HWACCEL_VAAPI: "{0} -hide_banner -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device {3} {1} -c:v h264_vaapi -g 50 -bf 0 -profile:v high -level:v 4.1 -sei:v 0 -an -vf format=vaapi|nv12,hwupload {2}",
"preset-intel-qsv-h264": "{0} -hide_banner {1} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {2}", "preset-intel-qsv-h264": "{0} -hide_banner {1} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {2}",
"preset-intel-qsv-h265": "{0} -hide_banner {1} -c:v h264_qsv -g 50 -bf 0 -profile:v main -level:v 4.1 -async_depth:v 1 {2}", "preset-intel-qsv-h265": "{0} -hide_banner {1} -c:v h264_qsv -g 50 -bf 0 -profile:v main -level:v 4.1 -async_depth:v 1 {2}",
FFMPEG_HWACCEL_NVIDIA: "{0} -hide_banner {1} {3} -c:v h264_nvenc -g 50 -profile:v high -level:v auto -preset:v p2 -tune:v ll {2}", FFMPEG_HWACCEL_NVIDIA: "{0} -hide_banner {1} -hwaccel device {3} -c:v h264_nvenc -g 50 -profile:v high -level:v auto -preset:v p2 -tune:v ll {2}",
"preset-jetson-h264": "{0} -hide_banner {1} -c:v h264_nvmpi -profile high {2}", "preset-jetson-h264": "{0} -hide_banner {1} -c:v h264_nvmpi -profile high {2}",
"preset-jetson-h265": "{0} -hide_banner {1} -c:v h264_nvmpi -profile main {2}", "preset-jetson-h265": "{0} -hide_banner {1} -c:v h264_nvmpi -profile main {2}",
FFMPEG_HWACCEL_RKMPP: "{0} -hide_banner {1} -c:v h264_rkmpp -profile:v high {2}", FFMPEG_HWACCEL_RKMPP: "{0} -hide_banner {1} -c:v h264_rkmpp -profile:v high {2}",
@ -246,7 +246,7 @@ def parse_preset_hardware_acceleration_scale(
",hwdownload,format=nv12,eq=gamma=1.4:gamma_weight=0.5" in scale ",hwdownload,format=nv12,eq=gamma=1.4:gamma_weight=0.5" in scale
and os.environ.get("FFMPEG_DISABLE_GAMMA_EQUALIZER") is not None and os.environ.get("FFMPEG_DISABLE_GAMMA_EQUALIZER") is not None
): ):
scale.replace( scale = scale.replace(
",hwdownload,format=nv12,eq=gamma=1.4:gamma_weight=0.5", ",hwdownload,format=nv12,eq=gamma=1.4:gamma_weight=0.5",
":format=nv12,hwdownload,format=nv12,format=yuv420p", ":format=nv12,hwdownload,format=nv12,format=yuv420p",
) )

View File

@ -1,7 +1,7 @@
"""Ollama Provider for Frigate AI.""" """Ollama Provider for Frigate AI."""
import logging import logging
from typing import Optional from typing import Any, Optional
from httpx import TimeoutException from httpx import TimeoutException
from ollama import Client as ApiClient from ollama import Client as ApiClient
@ -17,10 +17,24 @@ logger = logging.getLogger(__name__)
class OllamaClient(GenAIClient): class OllamaClient(GenAIClient):
"""Generative AI client for Frigate using Ollama.""" """Generative AI client for Frigate using Ollama."""
LOCAL_OPTIMIZED_OPTIONS = {
"options": {
"temperature": 0.5,
"repeat_penalty": 1.15,
"presence_penalty": 0.1,
},
}
provider: ApiClient provider: ApiClient
provider_options: dict[str, Any]
def _init_provider(self): def _init_provider(self):
"""Initialize the client.""" """Initialize the client."""
self.provider_options = {
**self.LOCAL_OPTIMIZED_OPTIONS,
**self.genai_config.provider_options,
}
try: try:
client = ApiClient(host=self.genai_config.base_url, timeout=self.timeout) client = ApiClient(host=self.genai_config.base_url, timeout=self.timeout)
# ensure the model is available locally # ensure the model is available locally
@ -48,7 +62,7 @@ class OllamaClient(GenAIClient):
self.genai_config.model, self.genai_config.model,
prompt, prompt,
images=images if images else None, images=images if images else None,
**self.genai_config.provider_options, **self.provider_options,
) )
return result["response"].strip() return result["response"].strip()
except (TimeoutException, ResponseError) as e: except (TimeoutException, ResponseError) as e:

View File

@ -2,12 +2,15 @@
import logging import logging
import os import os
import random
from collections import defaultdict
import cv2 import cv2
import numpy as np import numpy as np
from frigate.comms.embeddings_updater import EmbeddingsRequestEnum, EmbeddingsRequestor from frigate.comms.embeddings_updater import EmbeddingsRequestEnum, EmbeddingsRequestor
from frigate.comms.inter_process import InterProcessRequestor from frigate.comms.inter_process import InterProcessRequestor
from frigate.config import FfmpegConfig
from frigate.const import ( from frigate.const import (
CLIPS_DIR, CLIPS_DIR,
MODEL_CACHE_DIR, MODEL_CACHE_DIR,
@ -15,7 +18,10 @@ from frigate.const import (
UPDATE_MODEL_STATE, UPDATE_MODEL_STATE,
) )
from frigate.log import redirect_output_to_logger from frigate.log import redirect_output_to_logger
from frigate.models import Event, Recordings, ReviewSegment
from frigate.types import ModelStatusTypesEnum from frigate.types import ModelStatusTypesEnum
from frigate.util.image import get_image_from_recording
from frigate.util.path import get_event_thumbnail_bytes
from frigate.util.process import FrigateProcess from frigate.util.process import FrigateProcess
BATCH_SIZE = 16 BATCH_SIZE = 16
@ -69,6 +75,7 @@ class ClassificationTrainingProcess(FrigateProcess):
logger.info(f"Kicking off classification training for {self.model_name}.") logger.info(f"Kicking off classification training for {self.model_name}.")
dataset_dir = os.path.join(CLIPS_DIR, self.model_name, "dataset") dataset_dir = os.path.join(CLIPS_DIR, self.model_name, "dataset")
model_dir = os.path.join(MODEL_CACHE_DIR, self.model_name) model_dir = os.path.join(MODEL_CACHE_DIR, self.model_name)
os.makedirs(model_dir, exist_ok=True)
num_classes = len( num_classes = len(
[ [
d d
@ -139,7 +146,6 @@ class ClassificationTrainingProcess(FrigateProcess):
f.write(tflite_model) f.write(tflite_model)
@staticmethod
def kickoff_model_training( def kickoff_model_training(
embeddingRequestor: EmbeddingsRequestor, model_name: str embeddingRequestor: EmbeddingsRequestor, model_name: str
) -> None: ) -> None:
@ -172,3 +178,520 @@ def kickoff_model_training(
}, },
) )
requestor.stop() requestor.stop()
@staticmethod
def collect_state_classification_examples(
model_name: str, cameras: dict[str, tuple[float, float, float, float]]
) -> None:
"""
Collect representative state classification examples from review items.
This function:
1. Queries review items from specified cameras
2. Selects 100 balanced timestamps across the data
3. Extracts keyframes from recordings (cropped to specified regions)
4. Selects 20 most visually distinct images
5. Saves them to the dataset directory
Args:
model_name: Name of the classification model
cameras: Dict mapping camera names to normalized crop coordinates [x1, y1, x2, y2] (0-1)
"""
dataset_dir = os.path.join(CLIPS_DIR, model_name, "dataset")
temp_dir = os.path.join(dataset_dir, "temp")
os.makedirs(temp_dir, exist_ok=True)
# Step 1: Get review items for the cameras
camera_names = list(cameras.keys())
review_items = list(
ReviewSegment.select()
.where(ReviewSegment.camera.in_(camera_names))
.where(ReviewSegment.end_time.is_null(False))
.order_by(ReviewSegment.start_time.asc())
)
if not review_items:
logger.warning(f"No review items found for cameras: {camera_names}")
return
# Step 2: Create balanced timestamp selection (100 samples)
timestamps = _select_balanced_timestamps(review_items, target_count=100)
# Step 3: Extract keyframes from recordings with crops applied
keyframes = _extract_keyframes(
"/usr/lib/ffmpeg/7.0/bin/ffmpeg", timestamps, temp_dir, cameras
)
# Step 4: Select 24 most visually distinct images (they're already cropped)
distinct_images = _select_distinct_images(keyframes, target_count=24)
# Step 5: Save to train directory for later classification
train_dir = os.path.join(CLIPS_DIR, model_name, "train")
os.makedirs(train_dir, exist_ok=True)
saved_count = 0
for idx, image_path in enumerate(distinct_images):
dest_path = os.path.join(train_dir, f"example_{idx:03d}.jpg")
try:
img = cv2.imread(image_path)
if img is not None:
cv2.imwrite(dest_path, img)
saved_count += 1
except Exception as e:
logger.error(f"Failed to save image {image_path}: {e}")
import shutil
try:
shutil.rmtree(temp_dir)
except Exception as e:
logger.warning(f"Failed to clean up temp directory: {e}")
def _select_balanced_timestamps(
review_items: list[ReviewSegment], target_count: int = 100
) -> list[dict]:
"""
Select balanced timestamps from review items.
Strategy:
- Group review items by camera and time of day
- Sample evenly across groups to ensure diversity
- For each selected review item, pick a random timestamp within its duration
Returns:
List of dicts with keys: camera, timestamp, review_item
"""
# Group by camera and hour of day for temporal diversity
grouped = defaultdict(list)
for item in review_items:
camera = item.camera
# Group by 6-hour blocks for temporal diversity
hour_block = int(item.start_time // (6 * 3600))
key = f"{camera}_{hour_block}"
grouped[key].append(item)
# Calculate how many samples per group
num_groups = len(grouped)
if num_groups == 0:
return []
samples_per_group = max(1, target_count // num_groups)
timestamps = []
# Sample from each group
for group_items in grouped.values():
# Take samples_per_group items from this group
sample_size = min(samples_per_group, len(group_items))
sampled_items = random.sample(group_items, sample_size)
for item in sampled_items:
# Pick a random timestamp within the review item's duration
duration = item.end_time - item.start_time
if duration <= 0:
continue
# Sample from middle 80% to avoid edge artifacts
offset = random.uniform(duration * 0.1, duration * 0.9)
timestamp = item.start_time + offset
timestamps.append(
{
"camera": item.camera,
"timestamp": timestamp,
"review_item": item,
}
)
# If we don't have enough, sample more from larger groups
while len(timestamps) < target_count and len(timestamps) < len(review_items):
for group_items in grouped.values():
if len(timestamps) >= target_count:
break
# Pick a random item not already sampled
item = random.choice(group_items)
duration = item.end_time - item.start_time
if duration <= 0:
continue
offset = random.uniform(duration * 0.1, duration * 0.9)
timestamp = item.start_time + offset
# Check if we already have a timestamp near this one
if not any(abs(t["timestamp"] - timestamp) < 1.0 for t in timestamps):
timestamps.append(
{
"camera": item.camera,
"timestamp": timestamp,
"review_item": item,
}
)
return timestamps[:target_count]
def _extract_keyframes(
ffmpeg_path: str,
timestamps: list[dict],
output_dir: str,
camera_crops: dict[str, tuple[float, float, float, float]],
) -> list[str]:
"""
Extract keyframes from recordings at specified timestamps and crop to specified regions.
Args:
ffmpeg_path: Path to ffmpeg binary
timestamps: List of timestamp dicts from _select_balanced_timestamps
output_dir: Directory to save extracted frames
camera_crops: Dict mapping camera names to normalized crop coordinates [x1, y1, x2, y2] (0-1)
Returns:
List of paths to successfully extracted and cropped keyframe images
"""
keyframe_paths = []
for idx, ts_info in enumerate(timestamps):
camera = ts_info["camera"]
timestamp = ts_info["timestamp"]
if camera not in camera_crops:
logger.warning(f"No crop coordinates for camera {camera}")
continue
norm_x1, norm_y1, norm_x2, norm_y2 = camera_crops[camera]
try:
recording = (
Recordings.select()
.where(
(timestamp >= Recordings.start_time)
& (timestamp <= Recordings.end_time)
& (Recordings.camera == camera)
)
.order_by(Recordings.start_time.desc())
.limit(1)
.get()
)
except Exception:
continue
relative_time = timestamp - recording.start_time
try:
config = FfmpegConfig(path="/usr/lib/ffmpeg/7.0")
image_data = get_image_from_recording(
config,
recording.path,
relative_time,
codec="mjpeg",
height=None,
)
if image_data:
nparr = np.frombuffer(image_data, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
if img is not None:
height, width = img.shape[:2]
x1 = int(norm_x1 * width)
y1 = int(norm_y1 * height)
x2 = int(norm_x2 * width)
y2 = int(norm_y2 * height)
x1_clipped = max(0, min(x1, width))
y1_clipped = max(0, min(y1, height))
x2_clipped = max(0, min(x2, width))
y2_clipped = max(0, min(y2, height))
if x2_clipped > x1_clipped and y2_clipped > y1_clipped:
cropped = img[y1_clipped:y2_clipped, x1_clipped:x2_clipped]
resized = cv2.resize(cropped, (224, 224))
output_path = os.path.join(output_dir, f"frame_{idx:04d}.jpg")
cv2.imwrite(output_path, resized)
keyframe_paths.append(output_path)
except Exception as e:
logger.debug(
f"Failed to extract frame from {recording.path} at {relative_time}s: {e}"
)
continue
return keyframe_paths
def _select_distinct_images(
image_paths: list[str], target_count: int = 20
) -> list[str]:
"""
Select the most visually distinct images from a set of keyframes.
Uses a greedy algorithm based on image histograms:
1. Start with a random image
2. Iteratively add the image that is most different from already selected images
3. Difference is measured using histogram comparison
Args:
image_paths: List of paths to candidate images
target_count: Number of distinct images to select
Returns:
List of paths to selected images
"""
if len(image_paths) <= target_count:
return image_paths
histograms = {}
valid_paths = []
for path in image_paths:
try:
img = cv2.imread(path)
if img is None:
continue
hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)
hist = cv2.calcHist(
[hsv], [0, 1, 2], None, [8, 8, 8], [0, 180, 0, 256, 0, 256]
)
hist = cv2.normalize(hist, hist).flatten()
histograms[path] = hist
valid_paths.append(path)
except Exception as e:
logger.debug(f"Failed to process image {path}: {e}")
continue
if len(valid_paths) <= target_count:
return valid_paths
selected = []
first_image = random.choice(valid_paths)
selected.append(first_image)
remaining = [p for p in valid_paths if p != first_image]
while len(selected) < target_count and remaining:
max_min_distance = -1
best_candidate = None
for candidate in remaining:
min_distance = float("inf")
for selected_img in selected:
distance = cv2.compareHist(
histograms[candidate],
histograms[selected_img],
cv2.HISTCMP_BHATTACHARYYA,
)
min_distance = min(min_distance, distance)
if min_distance > max_min_distance:
max_min_distance = min_distance
best_candidate = candidate
if best_candidate:
selected.append(best_candidate)
remaining.remove(best_candidate)
else:
break
return selected
@staticmethod
def collect_object_classification_examples(
model_name: str,
label: str,
) -> None:
"""
Collect representative object classification examples from event thumbnails.
This function:
1. Queries events for the specified label
2. Selects 100 balanced events across different cameras and times
3. Retrieves thumbnails for selected events (with 33% center crop applied)
4. Selects 24 most visually distinct thumbnails
5. Saves to dataset directory
Args:
model_name: Name of the classification model
label: Object label to collect (e.g., "person", "car")
cameras: List of camera names to collect examples from
"""
dataset_dir = os.path.join(CLIPS_DIR, model_name, "dataset")
temp_dir = os.path.join(dataset_dir, "temp")
os.makedirs(temp_dir, exist_ok=True)
# Step 1: Query events for the specified label and cameras
events = list(
Event.select().where((Event.label == label)).order_by(Event.start_time.asc())
)
if not events:
logger.warning(f"No events found for label '{label}'")
return
logger.debug(f"Found {len(events)} events")
# Step 2: Select balanced events (100 samples)
selected_events = _select_balanced_events(events, target_count=100)
logger.debug(f"Selected {len(selected_events)} events")
# Step 3: Extract thumbnails from events
thumbnails = _extract_event_thumbnails(selected_events, temp_dir)
logger.debug(f"Successfully extracted {len(thumbnails)} thumbnails")
# Step 4: Select 24 most visually distinct thumbnails
distinct_images = _select_distinct_images(thumbnails, target_count=24)
logger.debug(f"Selected {len(distinct_images)} distinct images")
# Step 5: Save to train directory for later classification
train_dir = os.path.join(CLIPS_DIR, model_name, "train")
os.makedirs(train_dir, exist_ok=True)
saved_count = 0
for idx, image_path in enumerate(distinct_images):
dest_path = os.path.join(train_dir, f"example_{idx:03d}.jpg")
try:
img = cv2.imread(image_path)
if img is not None:
cv2.imwrite(dest_path, img)
saved_count += 1
except Exception as e:
logger.error(f"Failed to save image {image_path}: {e}")
import shutil
try:
shutil.rmtree(temp_dir)
except Exception as e:
logger.warning(f"Failed to clean up temp directory: {e}")
logger.debug(
f"Successfully collected {saved_count} classification examples in {train_dir}"
)
def _select_balanced_events(
events: list[Event], target_count: int = 100
) -> list[Event]:
"""
Select balanced events from the event list.
Strategy:
- Group events by camera and time of day
- Sample evenly across groups to ensure diversity
- Prioritize events with higher scores
Returns:
List of selected events
"""
grouped = defaultdict(list)
for event in events:
camera = event.camera
hour_block = int(event.start_time // (6 * 3600))
key = f"{camera}_{hour_block}"
grouped[key].append(event)
num_groups = len(grouped)
if num_groups == 0:
return []
samples_per_group = max(1, target_count // num_groups)
selected = []
for group_events in grouped.values():
sorted_events = sorted(
group_events,
key=lambda e: e.data.get("score", 0) if e.data else 0,
reverse=True,
)
sample_size = min(samples_per_group, len(sorted_events))
selected.extend(sorted_events[:sample_size])
if len(selected) < target_count:
remaining = [e for e in events if e not in selected]
remaining_sorted = sorted(
remaining,
key=lambda e: e.data.get("score", 0) if e.data else 0,
reverse=True,
)
needed = target_count - len(selected)
selected.extend(remaining_sorted[:needed])
return selected[:target_count]
def _extract_event_thumbnails(events: list[Event], output_dir: str) -> list[str]:
"""
Extract thumbnails from events and save to disk.
Args:
events: List of Event objects
output_dir: Directory to save thumbnails
Returns:
List of paths to successfully extracted thumbnail images
"""
thumbnail_paths = []
for idx, event in enumerate(events):
try:
thumbnail_bytes = get_event_thumbnail_bytes(event)
if thumbnail_bytes:
nparr = np.frombuffer(thumbnail_bytes, np.uint8)
img = cv2.imdecode(nparr, cv2.IMREAD_COLOR)
if img is not None:
height, width = img.shape[:2]
crop_size = 1.0
if event.data and "box" in event.data and "region" in event.data:
box = event.data["box"]
region = event.data["region"]
if len(box) == 4 and len(region) == 4:
box_w, box_h = box[2], box[3]
region_w, region_h = region[2], region[3]
box_area = (box_w * box_h) / (region_w * region_h)
if box_area < 0.05:
crop_size = 0.4
elif box_area < 0.10:
crop_size = 0.5
elif box_area < 0.20:
crop_size = 0.65
elif box_area < 0.35:
crop_size = 0.80
else:
crop_size = 0.95
crop_width = int(width * crop_size)
crop_height = int(height * crop_size)
x1 = (width - crop_width) // 2
y1 = (height - crop_height) // 2
x2 = x1 + crop_width
y2 = y1 + crop_height
cropped = img[y1:y2, x1:x2]
resized = cv2.resize(cropped, (224, 224))
output_path = os.path.join(output_dir, f"thumbnail_{idx:04d}.jpg")
cv2.imwrite(output_path, resized)
thumbnail_paths.append(output_path)
except Exception as e:
logger.debug(f"Failed to extract thumbnail for event {event.id}: {e}")
continue
return thumbnail_paths

View File

@ -577,7 +577,7 @@ def ffprobe_stream(ffmpeg, path: str, detailed: bool = False) -> sp.CompletedPro
if detailed and format_entries: if detailed and format_entries:
ffprobe_cmd.extend(["-show_entries", f"format={format_entries}"]) ffprobe_cmd.extend(["-show_entries", f"format={format_entries}"])
ffprobe_cmd.extend(["-loglevel", "quiet", clean_path]) ffprobe_cmd.extend(["-loglevel", "error", clean_path])
return sp.run(ffprobe_cmd, capture_output=True) return sp.run(ffprobe_cmd, capture_output=True)

View File

@ -207,6 +207,14 @@
"length": { "length": {
"feet": "peus", "feet": "peus",
"meters": "metres" "meters": "metres"
},
"data": {
"kbps": "Kb/s",
"mbps": "Mb/s",
"gbps": "Gb/s",
"kbph": "kB/hora",
"mbph": "MB/hora",
"gbph": "GB/hora"
} }
}, },
"label": { "label": {
@ -270,5 +278,8 @@
"desc": "Pàgina no trobada" "desc": "Pàgina no trobada"
}, },
"selectItem": "Selecciona {{item}}", "selectItem": "Selecciona {{item}}",
"readTheDocumentation": "Llegir la documentació" "readTheDocumentation": "Llegir la documentació",
"information": {
"pixels": "{{area}}px"
}
} }

View File

@ -98,7 +98,8 @@
"button": { "button": {
"deleteNow": "Suprimir ara", "deleteNow": "Suprimir ara",
"export": "Exportar", "export": "Exportar",
"markAsReviewed": "Marcar com a revisat" "markAsReviewed": "Marcar com a revisat",
"markAsUnreviewed": "Marcar com no revisat"
}, },
"confirmDelete": { "confirmDelete": {
"title": "Confirmar la supressió", "title": "Confirmar la supressió",

View File

@ -130,6 +130,9 @@
"playInBackground": { "playInBackground": {
"label": "Reproduir en segon pla", "label": "Reproduir en segon pla",
"tips": "Habilita aquesta opció per a contiuar la transmissió tot i que el reproductor estigui ocult." "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ó."
} }
}, },
"streamingSettings": "Paràmetres de transmissió", "streamingSettings": "Paràmetres de transmissió",
@ -167,5 +170,14 @@
"transcription": { "transcription": {
"enable": "Habilita la transcripció d'àudio en temps real", "enable": "Habilita la transcripció d'àudio en temps real",
"disable": "Deshabilita la transcripció d'àudio en temps real" "disable": "Deshabilita la transcripció d'àudio en temps real"
},
"snapshot": {
"takeSnapshot": "Descarregar una instantània",
"noVideoSource": "No hi ha cap font de video per fer una instantània.",
"captureFailed": "Error capturant una instantània.",
"downloadStarted": "Inici de baixada d'instantània."
},
"noCameras": {
"title": "Sense càmeres per configurar"
} }
} }

View File

@ -9,7 +9,9 @@
"masksAndZones": "Editor de màscares i zones - Frigate", "masksAndZones": "Editor de màscares i zones - Frigate",
"general": "Paràmetres Generals - Frigate", "general": "Paràmetres Generals - Frigate",
"frigatePlus": "Paràmetres de Frigate+ - Frigate", "frigatePlus": "Paràmetres de Frigate+ - Frigate",
"notifications": "Paràmetres de notificació - Frigate" "notifications": "Paràmetres de notificació - Frigate",
"cameraManagement": "Gestionar càmeres - Frigate",
"cameraReview": "Configuració Revisió de Càmeres - Frigate"
}, },
"menu": { "menu": {
"ui": "Interfície d'usuari", "ui": "Interfície d'usuari",
@ -21,7 +23,10 @@
"debug": "Depuració", "debug": "Depuració",
"frigateplus": "Frigate+", "frigateplus": "Frigate+",
"enrichments": "Enriquiments", "enrichments": "Enriquiments",
"triggers": "Disparadors" "triggers": "Disparadors",
"cameraManagement": "Gestió",
"cameraReview": "Revisió",
"roles": "Rols"
}, },
"dialog": { "dialog": {
"unsavedChanges": { "unsavedChanges": {
@ -825,5 +830,16 @@
"userUpdateFailed": "Error a l'actualitzar els ros d'usuari: {{errorMessage}}" "userUpdateFailed": "Error a l'actualitzar els ros d'usuari: {{errorMessage}}"
} }
} }
},
"cameraWizard": {
"title": "Afegir C àmera",
"description": "Seguiu els passos de sota per afegir una nova càmera a la instal·lació.",
"steps": {
"nameAndConnection": "Nom i connexió",
"streamConfiguration": "Configuració de stream"
},
"step1": {
"cameraBrand": "Marca de la càmera"
}
} }
} }

View File

@ -10,7 +10,8 @@
"object": "Ladění - Frigate", "object": "Ladění - Frigate",
"general": "Obecné nastavení - Frigate", "general": "Obecné nastavení - Frigate",
"frigatePlus": "Frigate+ nastavení - Frigate", "frigatePlus": "Frigate+ nastavení - Frigate",
"enrichments": "Nastavení obohacení - Frigate" "enrichments": "Nastavení obohacení - Frigate",
"cameraManagement": "Správa kamer - Frigate"
}, },
"frigatePlus": { "frigatePlus": {
"toast": { "toast": {

View File

@ -232,6 +232,14 @@
"length": { "length": {
"feet": "Fuß", "feet": "Fuß",
"meters": "Meter" "meters": "Meter"
},
"data": {
"kbps": "kB/s",
"mbps": "MB/s",
"gbps": "GB/s",
"kbph": "kB/Stunde",
"mbph": "MB/Stunde",
"gbph": "GB/Stunde"
} }
}, },
"toast": { "toast": {
@ -273,5 +281,8 @@
"desc": "Du hast keine Berechtigung diese Seite anzuzeigen.", "desc": "Du hast keine Berechtigung diese Seite anzuzeigen.",
"documentTitle": "Zugang verweigert - Frigate", "documentTitle": "Zugang verweigert - Frigate",
"title": "Zugang verweigert" "title": "Zugang verweigert"
},
"information": {
"pixels": "{{area}}px"
} }
} }

View File

@ -117,7 +117,8 @@
"button": { "button": {
"export": "Exportieren", "export": "Exportieren",
"markAsReviewed": "Als geprüft markieren", "markAsReviewed": "Als geprüft markieren",
"deleteNow": "Jetzt löschen" "deleteNow": "Jetzt löschen",
"markAsUnreviewed": "Als ungeprüft markieren"
} }
}, },
"imagePicker": { "imagePicker": {

View File

@ -27,7 +27,7 @@
"donut": "Donut", "donut": "Donut",
"cake": "Kuchen", "cake": "Kuchen",
"chair": "Stuhl", "chair": "Stuhl",
"couch": "Couch", "couch": "Sofa",
"bed": "Bett", "bed": "Bett",
"dining_table": "Esstisch", "dining_table": "Esstisch",
"toilet": "Toilette", "toilet": "Toilette",

View File

@ -29,7 +29,7 @@
"selectFace": "Wähle Gesicht", "selectFace": "Wähle Gesicht",
"imageEntry": { "imageEntry": {
"dropActive": "Ziehe das Bild hierher…", "dropActive": "Ziehe das Bild hierher…",
"dropInstructions": "Ziehe ein Bild hier her oder klicke um eines auszuwählen", "dropInstructions": "Ziehe ein Bild hier her, füge es ein oder klicke um eines auszuwählen",
"maxSize": "Maximale Größe: {{size}} MB", "maxSize": "Maximale Größe: {{size}} MB",
"validation": { "validation": {
"selectImage": "Bitte wähle ein Bild aus." "selectImage": "Bitte wähle ein Bild aus."

View File

@ -30,16 +30,16 @@
}, },
"zoom": { "zoom": {
"in": { "in": {
"label": "PTZ-Kamera vergrößern" "label": "PTZ-Kamera rein zoomen"
}, },
"out": { "out": {
"label": "PTZ-Kamera herauszoomen" "label": "PTZ-Kamera heraus zoomen"
} }
}, },
"presets": "PTZ-Kameravoreinstellungen", "presets": "PTZ-Kamera Voreinstellungen",
"frame": { "frame": {
"center": { "center": {
"label": "Klicken Sie in den Rahmen, um die PTZ-Kamera zu zentrieren" "label": "Klicke in den Rahmen, um die PTZ-Kamera zu zentrieren"
} }
}, },
"focus": { "focus": {
@ -62,8 +62,8 @@
"enable": "Aufzeichnung aktivieren" "enable": "Aufzeichnung aktivieren"
}, },
"snapshots": { "snapshots": {
"enable": "Snapshots aktivieren", "enable": "Schnappschüsse aktivieren",
"disable": "Snapshots deaktivieren" "disable": "Schnappschüsse deaktivieren"
}, },
"autotracking": { "autotracking": {
"disable": "Autotracking deaktivieren", "disable": "Autotracking deaktivieren",
@ -74,7 +74,7 @@
"disable": "Stream-Statistiken ausblenden" "disable": "Stream-Statistiken ausblenden"
}, },
"manualRecording": { "manualRecording": {
"title": "On-Demand Aufzeichnung", "title": "On-Demand",
"showStats": { "showStats": {
"label": "Statistiken anzeigen", "label": "Statistiken anzeigen",
"desc": "Aktivieren Sie diese Option, um Stream-Statistiken als Overlay über dem Kamera-Feed anzuzeigen." "desc": "Aktivieren Sie diese Option, um Stream-Statistiken als Overlay über dem Kamera-Feed anzuzeigen."
@ -88,7 +88,7 @@
"desc": "Aktivieren Sie diese Option, um das Streaming fortzusetzen, wenn der Player ausgeblendet ist.", "desc": "Aktivieren Sie diese Option, um das Streaming fortzusetzen, wenn der Player ausgeblendet ist.",
"label": "Im Hintergrund abspielen" "label": "Im Hintergrund abspielen"
}, },
"tips": "Starten Sie ein manuelles Ereignis basierend auf den Aufzeichnung Aufbewahrungseinstellungen dieser Kamera.", "tips": "Lade einen Sofort-Schnappschuss herunter oder starte ein manuelles Ereignis basierend auf den Aufbewahrungseinstellungen für Aufzeichnungen dieser Kamera.",
"debugView": "Debug-Ansicht", "debugView": "Debug-Ansicht",
"start": "On-Demand Aufzeichnung starten", "start": "On-Demand Aufzeichnung starten",
"failedToEnd": "Die manuelle On-Demand Aufzeichnung konnte nicht beendet werden." "failedToEnd": "Die manuelle On-Demand Aufzeichnung konnte nicht beendet werden."
@ -118,6 +118,9 @@
"playInBackground": { "playInBackground": {
"tips": "Aktivieren Sie diese Option, um das Streaming fortzusetzen, wenn der Player ausgeblendet ist.", "tips": "Aktivieren Sie diese Option, um das Streaming fortzusetzen, wenn der Player ausgeblendet ist.",
"label": "Im Hintergrund abspielen" "label": "Im Hintergrund abspielen"
},
"debug": {
"picker": "Stream Auswahl nicht verfügbar im Debug Modus. Die Debug Ansicht nutzt immer den Stream, welcher der Rolle zugewiesen ist."
} }
}, },
"effectiveRetainMode": { "effectiveRetainMode": {
@ -167,5 +170,16 @@
"transcription": { "transcription": {
"enable": "Live Audio Transkription einschalten", "enable": "Live Audio Transkription einschalten",
"disable": "Live Audio Transkription ausschalten" "disable": "Live Audio Transkription ausschalten"
},
"noCameras": {
"title": "Keine Kameras eingerichtet",
"description": "Beginne indem du eine Kamera anschließt.",
"buttonText": "Kamera hinzufügen"
},
"snapshot": {
"takeSnapshot": "Sofort-Schnappschuss herunterladen",
"noVideoSource": "Keine Video-Quelle für Schnappschuss verfügbar.",
"captureFailed": "Die Aufnahme des Schnappschusses ist fehlgeschlagen.",
"downloadStarted": "Schnappschuss Download gestartet."
} }
} }

View File

@ -10,7 +10,9 @@
"classification": "Klassifizierungseinstellungen Frigate", "classification": "Klassifizierungseinstellungen Frigate",
"motionTuner": "Bewegungserkennungs-Optimierer Frigate", "motionTuner": "Bewegungserkennungs-Optimierer Frigate",
"notifications": "Benachrichtigungs-Einstellungen", "notifications": "Benachrichtigungs-Einstellungen",
"enrichments": "Erweiterte Statistiken - Frigate" "enrichments": "Erweiterte Statistiken - Frigate",
"cameraManagement": "Kameras verwalten - Frigate",
"cameraReview": "Kamera Einstellungen prüfen - Frigate"
}, },
"menu": { "menu": {
"ui": "Benutzeroberfläche", "ui": "Benutzeroberfläche",
@ -23,7 +25,10 @@
"users": "Benutzer", "users": "Benutzer",
"notifications": "Benachrichtigungen", "notifications": "Benachrichtigungen",
"enrichments": "Erkennungsfunktionen", "enrichments": "Erkennungsfunktionen",
"triggers": "Auslöser" "triggers": "Auslöser",
"roles": "Rollen",
"cameraManagement": "Verwaltung",
"cameraReview": "Überprüfung"
}, },
"dialog": { "dialog": {
"unsavedChanges": { "unsavedChanges": {
@ -69,7 +74,7 @@
"title": "Kalender", "title": "Kalender",
"firstWeekday": { "firstWeekday": {
"label": "Erster Wochentag", "label": "Erster Wochentag",
"desc": "Der Tag, an dem die Wochen des Review Kalenders beginnen.", "desc": "Der Tag, an dem die Wochen des Überprüfungs-Kalenders beginnen.",
"sunday": "Sonntag", "sunday": "Sonntag",
"monday": "Montag" "monday": "Montag"
} }
@ -812,6 +817,11 @@
"error": { "error": {
"min": "Mindesten eine Aktion muss ausgewählt sein." "min": "Mindesten eine Aktion muss ausgewählt sein."
} }
},
"friendly_name": {
"title": "Nutzerfreundlicher Name",
"placeholder": "Benenne oder beschreibe diesen Auslöser",
"description": "Ein optionaler nutzerfreundlicher Name oder eine Beschreibung für diesen Auslöser."
} }
} }
}, },
@ -826,6 +836,10 @@
"updateTriggerFailed": "Auslöser könnte nicht aktualisiert werden: {{errorMessage}}", "updateTriggerFailed": "Auslöser könnte nicht aktualisiert werden: {{errorMessage}}",
"deleteTriggerFailed": "Auslöser konnte nicht gelöscht werden: {{errorMessage}}" "deleteTriggerFailed": "Auslöser konnte nicht gelöscht werden: {{errorMessage}}"
} }
},
"semanticSearch": {
"title": "Semantische Suche ist deaktiviert",
"desc": "Semantische Suche muss aktiviert sein um Auslöser nutzen zu können."
} }
}, },
"roles": { "roles": {
@ -887,5 +901,222 @@
"userUpdateFailed": "Aktualisierung der Benutzerrollen fehlgeschlagen: {{errorMessage}}" "userUpdateFailed": "Aktualisierung der Benutzerrollen fehlgeschlagen: {{errorMessage}}"
} }
} }
},
"cameraWizard": {
"title": "Kamera hinzufügen",
"description": "Folge den Anweisungen unten, um eine neue Kamera zu deiner Frigate-Installation hinzuzufügen.",
"steps": {
"nameAndConnection": "Name & Verbindung",
"streamConfiguration": "Stream Konfiguration",
"validationAndTesting": "Überprüfung & Testen"
},
"save": {
"success": "Neue Kamera {{cameraName}} erfolgreich hinzugefügt.",
"failure": "Fehler beim Speichern von {{cameraName}}."
},
"testResultLabels": {
"resolution": "Auflösung",
"video": "Video",
"audio": "Audio",
"fps": "FPS"
},
"commonErrors": {
"noUrl": "Bitte korrekte Stream-URL eingeben",
"testFailed": "Stream Test fehlgeschlagen: {{error}}"
},
"step1": {
"description": "Gib deine Kameradaten ein und teste die Verbindung.",
"cameraName": "Kamera-Name",
"cameraNamePlaceholder": "z.B. vordere_tür oder Hof Übersicht",
"host": "Host/IP Adresse",
"port": "Port",
"username": "Nutzername",
"usernamePlaceholder": "Optional",
"password": "Passwort",
"passwordPlaceholder": "Optional",
"selectTransport": "Transport-Protokoll auswählen",
"cameraBrand": "Kamera-Hersteller",
"selectBrand": "Wähle die Kamera-Hersteller für die URL-Vorlage aus",
"customUrl": "Benutzerdefinierte Stream-URL",
"brandInformation": "Hersteller Information",
"brandUrlFormat": "Für Kameras mit RTSP URL nutze folgendes Format: {{exampleUrl}}",
"customUrlPlaceholder": "rtsp://nutzername:passwort@host:port/pfad",
"testConnection": "Teste Verbindung",
"testSuccess": "Verbindungstest erfolgreich!",
"testFailed": "Verbindungstest fehlgeschlagen. Bitte prüfe deine Eingaben und versuche es erneut.",
"streamDetails": "Stream Details",
"warnings": {
"noSnapshot": "Es kann kein Snapshot aus dem konfigurierten Stream abgerufen werden."
},
"errors": {
"brandOrCustomUrlRequired": "Wählen Sie entweder einen Kamera-Hersteller mit Host/IP aus oder wählen Sie „Andere“ mit einer benutzerdefinierten URL",
"nameRequired": "Kamera-Name benötigt",
"nameLength": "Kamera-Name darf höchsten 64 Zeichen lang sein",
"invalidCharacters": "Kamera-Name enthält ungültige Zeichen",
"nameExists": "Kamera-Name existiert bereits",
"brands": {
"reolink-rtsp": "Reolink RTSP wird nicht empfohlen. Es wird empfohlen, http in den Kameraeinstellungen zu aktivieren und den Kamera-Assistenten neu zu starten."
}
},
"docs": {
"reolink": "https://docs.frigate.video/configuration/camera_specific.html#reolink-cameras"
}
},
"step2": {
"description": "Konfigurieren Sie Stream-Rollen und fügen Sie zusätzliche Streams für Ihre Kamera hinzu.",
"streamsTitle": "Kamera Streams",
"addStream": "Stream hinzufügen",
"addAnotherStream": "Weiteren Stream hinzufügen",
"streamTitle": "Stream {{nummer}}",
"streamUrl": "Stream URL",
"streamUrlPlaceholder": "rtsp://nutzername:passwort@host:port/pfad",
"url": "URL",
"resolution": "Auflösung",
"selectResolution": "Auflösung auswählen",
"quality": "Qualität",
"selectQuality": "Qualität auswählen",
"roles": "Rollen",
"roleLabels": {
"detect": "Objekt-Erkennung",
"record": "Aufzeichnung",
"audio": "Audio"
},
"testStream": "Verbindung testen",
"testSuccess": "Stream erfolgreich getestet!",
"testFailed": "Stream-Test fehlgeschlagen",
"testFailedTitle": "Test fehlgeschlagen",
"connected": "Verbunden",
"notConnected": "Nicht verbunden",
"featuresTitle": "Funktionen",
"go2rtc": "Verbindungen zur Kamera reduzieren",
"detectRoleWarning": "Mindestens ein Stream muss die Rolle „detect“ haben, um fortfahren zu können.",
"rolesPopover": {
"title": "Stream Rollen",
"detect": "Haupt-Feed für Objekt-Erkennung.",
"record": "Speichert Segmente des Video-Feeds basierend auf den Konfigurationseinstellungen.",
"audio": "Feed für audiobasierte Erkennung."
},
"featuresPopover": {
"title": "Stream Funktionen",
"description": "Verwende go2rtc Restreaming, um die Verbindungen zu deiner Kamera zu reduzieren."
}
},
"step3": {
"description": "Endgültige Validierung und Analyse vor dem Speichern Ihrer neuen Kamera. Verbinde jeden Stream vor dem Speichern.",
"validationTitle": "Stream Validierung",
"connectAllStreams": "Verbinde alle Streams",
"reconnectionSuccess": "Wiederverbindung erfolgreich.",
"reconnectionPartial": "Einige Streams konnten nicht wieder verbunden werden.",
"streamUnavailable": "Stream-Vorschau nicht verfügbar",
"reload": "Neu laden",
"connecting": "Verbinde...",
"streamTitle": "Stream {{number}}",
"valid": "Gültig",
"failed": "Fehlgeschlagen",
"notTested": "Nicht getestet",
"connectStream": "Verbinden",
"connectingStream": "Verbinde",
"disconnectStream": "Trennen",
"estimatedBandwidth": "Geschätzte Bandbreite",
"roles": "Rollen",
"none": "Keine",
"error": "Fehler",
"streamValidated": "Stream {{number}} wurde erfolgreich validiert",
"streamValidationFailed": "Stream {{number}} Validierung fehlgeschlagen",
"saveAndApply": "Neue Kamera speichern",
"saveError": "Ungültige Konfiguration. Bitte prüfe die Einstellungen.",
"issues": {
"title": "Stream Validierung",
"videoCodecGood": "Video-Codec ist {{codec}}.",
"audioCodecGood": "Audio-Codec ist {{codec}}.",
"noAudioWarning": "Für diesen Stream wurde kein Ton erkannt, die Aufzeichnungen enthalten keinen Ton.",
"audioCodecRecordError": "Der AAC-Audio-Codec ist erforderlich, um Audio in Aufnahmen zu unterstützen.",
"audioCodecRequired": "Ein Audiostream ist erforderlich, um Audioerkennung zu unterstützen.",
"restreamingWarning": "Eine Reduzierung der Verbindungen zur Kamera für den Aufzeichnungsstream kann zu einer etwas höheren CPU-Auslastung führen.",
"dahua": {
"substreamWarning": "Substream 1 ist auf eine niedrige Auflösung festgelegt. Viele Kameras von Dahua / Amcrest / EmpireTech unterstützen zusätzliche Substreams, die in den Kameraeinstellungen aktiviert werden müssen. Es wird empfohlen, diese Streams zu nutzen, sofern sie verfügbar sind."
},
"hikvision": {
"substreamWarning": "Substream 1 ist auf eine niedrige Auflösung festgelegt. Viele Hikvision-Kameras unterstützen zusätzliche Substreams, die in den Kameraeinstellungen aktiviert werden müssen. Es wird empfohlen, diese Streams zu nutzen, sofern sie verfügbar sind."
}
}
}
},
"cameraManagement": {
"title": "Kameras verwalten",
"addCamera": "Neue Kamera hinzufügen",
"editCamera": "Kamera bearbeiten:",
"selectCamera": "Wähle eine Kamera",
"backToSettings": "Zurück zu Kamera-Einstellungen",
"streams": {
"title": "Kameras aktivieren / deaktivieren",
"desc": "Deaktiviere eine Kamera vorübergehend, bis Frigate neu gestartet wird. Deaktivierung einer Kamera stoppt die Verarbeitung der Streams dieser Kamera durch Frigate vollständig. Erkennung, Aufzeichnung und Debugging sind dann nicht mehr verfügbar. <br /> <em>Hinweis: Dies deaktiviert nicht die go2rtc restreams.</em>"
},
"cameraConfig": {
"add": "Kamera hinzufügen",
"edit": "Kamera bearbeiten",
"description": "Konfiguriere die Kameraeinstellungen, einschließlich Streams und Rollen.",
"name": "Kamera-Name",
"nameRequired": "Kamera-Name benötigt",
"nameLength": "Kamera-Name darf maximal 64 Zeichen lang sein.",
"namePlaceholder": "z.B. vordere_tür oder Hof Übersicht",
"enabled": "Aktiviert",
"ffmpeg": {
"inputs": "Eingang Streams",
"path": "Stream-Pfad",
"pathRequired": "Stream-Pfad benötigt",
"pathPlaceholder": "rtsp://...",
"roles": "Rollen",
"rolesRequired": "Mindestens eine Rolle wird benötigt",
"rolesUnique": "Jede Rolle (audio, detect, record) kann nur einem Stream zugewiesen werden",
"addInput": "Eingangs-Stream hinzufügen",
"removeInput": "Eingangs-Stream entfernen",
"inputsRequired": "Es wird mindestens ein Eingangs-Stream benötigt"
},
"go2rtcStreams": "go2rtc Streams",
"streamUrls": "Stream URLs",
"addUrl": "URL hinzufügen",
"addGo2rtcStream": "go2rtc Stream hinzufügen",
"toast": {
"success": "Kamera {{cameraName}} erfolgreich gespeichert"
}
}
},
"cameraReview": {
"title": "Kamera-Einstellungen überprüfen",
"object_descriptions": {
"title": "Generative KI Objektbeschreibungen",
"desc": "Aktiviere/deaktiviere vorübergehend die Objektbeschreibungen durch Generative KI für diese Kamera. Wenn diese Option deaktiviert ist, werden keine KI-generierten Beschreibungen für verfolgte Objekte dieser Kamera erstellt."
},
"review_descriptions": {
"title": "Generative KI Review Beschreibungen",
"desc": "Generative KI Review Beschreibungen für diese Kamera vorübergehend aktivieren/deaktivieren. Wenn diese Option deaktiviert ist, werden für die Review Elemente dieser Kamera keine KI-generierten Beschreibungen angefordert."
},
"review": {
"title": "Review",
"desc": "Aktivieren/deaktivieren Sie vorübergehend Warnmeldungen und Erkennungen für diese Kamera, bis Frigate neu gestartet wird. Wenn diese Funktion deaktiviert ist, werden keine neuen Überprüfungselemente generiert. ",
"alerts": "Warnungen ",
"detections": "Erkennungen "
},
"reviewClassification": {
"title": "Bewertungsklassifizierung",
"desc": "Frigate kategorisiert zu überprüfende Elemente als Warnmeldungen und Erkennungen. Standardmäßig werden alle Objekte vom Typ <em>person</em> und <em>car</em> als Warnmeldungen betrachtet. Sie können die Kategorisierung der zu überprüfenden Elemente verfeinern, indem Sie die erforderlichen Zonen für sie konfigurieren.",
"noDefinedZones": "Für diese Kamera sind keine Zonen definiert.",
"objectAlertsTips": "Alle {{alertsLabels}}-Objekte auf {{cameraName}} werden als Warnmeldungen angezeigt.",
"zoneObjectAlertsTips": "Alle {{alertsLabels}}-Objekte, die in {{zone}} auf {{cameraName}} erkannt wurden, werden als Warnmeldungen angezeigt.",
"objectDetectionsTips": "Alle {{detectionsLabels}}-Objekte, die nicht unter {{cameraName}} kategorisiert sind, werden unabhängig davon, in welcher Zone sie sich befinden, als Erkennungen angezeigt.",
"zoneObjectDetectionsTips": {
"text": "Alle {{detectionsLabels}}-Objekte, die nicht in {{zone}} auf {{cameraName}} kategorisiert sind, werden als Erkennungen angezeigt.",
"notSelectDetections": "Alle {{detectionsLabels}}-Objekte, die in {{zone}} auf {{cameraName}} erkannt und nicht als Warnmeldungen kategorisiert wurden, werden unabhängig davon, in welcher Zone sie sich befinden, als Erkennungen angezeigt.",
"regardlessOfZoneObjectDetectionsTips": "Alle {{detectionsLabels}}-Objekte, die nicht unter {{cameraName}} kategorisiert sind, werden unabhängig davon, in welcher Zone sie sich befinden, als Erkennungen angezeigt."
},
"unsavedChanges": "Nicht gespeicherte Überprüfung der Klassifizierungseinstellungen für {{camera}}",
"selectAlertsZones": "Zonen für Warnmeldungen auswählen",
"selectDetectionsZones": "Zonen für Erkennungen auswählen",
"limitDetections": "Erkennungen auf bestimmte Zonen beschränken",
"toast": {
"success": "Die Konfiguration der Bewertungsklassifizierung wurde gespeichert. Starten Sie Frigate neu, um die Änderungen zu übernehmen."
}
}
} }
} }

View File

@ -1,10 +1,10 @@
{ {
"time": { "time": {
"untilForTime": "Ως{{time}}", "untilForTime": "Ως {{time}}",
"untilForRestart": "Μέχρι να γίνει επανεκίννηση του Frigate.", "untilForRestart": "Μέχρι να γίνει επανεκίννηση του Frigate.",
"untilRestart": "Μέχρι να γίνει επανεκκίνηση", "untilRestart": "Μέχρι να γίνει επανεκκίνηση",
"justNow": "Μόλις τώρα", "justNow": "Μόλις τώρα",
"ago": "{{timeAgo}} Πριν", "ago": "Πριν {{timeAgo}}",
"today": "Σήμερα", "today": "Σήμερα",
"yesterday": "Εχθές", "yesterday": "Εχθές",
"last7": "Τελευταίες 7 ημέρες", "last7": "Τελευταίες 7 ημέρες",
@ -31,7 +31,44 @@
"lastMonth": "Τελευταίος Μήνας", "lastMonth": "Τελευταίος Μήνας",
"5minutes": "5 λεπτά", "5minutes": "5 λεπτά",
"10minutes": "10 λεπτά", "10minutes": "10 λεπτά",
"30minutes": "30 λεπτά" "30minutes": "30 λεπτά",
"1hour": "1 ώρα",
"12hours": "12 ώρες",
"24hours": "24 ώρες",
"pm": "μ.μ.",
"formattedTimestamp": {
"12hour": "d MMM, h:mm:ss aaa",
"24hour": "d MMM, HH:mm:ss"
},
"formattedTimestamp2": {
"12hour": "MM/dd h:mm:ssa",
"24hour": "d MMM HH:mm:ss"
},
"formattedTimestampHourMinute": {
"12hour": "h:mm aaa",
"24hour": "HH:mm"
},
"formattedTimestampHourMinuteSecond": {
"12hour": "h:mm:ss aaa",
"24hour": "HH:mm:ss"
},
"formattedTimestampMonthDayHourMinute": {
"12hour": "d MMM, h:mm aaa",
"24hour": "d MMM, HH:mm"
},
"formattedTimestampMonthDayYear": {
"12hour": "d MMM yyyy",
"24hour": "d MMM yyyy"
},
"formattedTimestampMonthDayYearHourMinute": {
"12hour": "d MMM yyyy, h:mm aaa",
"24hour": "d MMM yyyy, HH:mm"
},
"formattedTimestampMonthDay": "d MMM",
"formattedTimestampFilename": {
"12hour": "dd-MM-yy-h-mm-ss-a",
"24hour": "dd-MM-yy-HH-mm-ss"
}
}, },
"menu": { "menu": {
"live": { "live": {
@ -40,5 +77,49 @@
"count_other": "{{count}} Κάμερες" "count_other": "{{count}} Κάμερες"
} }
} }
},
"button": {
"save": "Αποθήκευση",
"apply": "Εφαρμογή",
"reset": "Επαναφορά",
"done": "Τέλος",
"enabled": "Ενεργοποιημένο",
"enable": "Ενεργοποίηση",
"disabled": "Απενεργοποιημένο",
"disable": "Απενεργοποίηση",
"saving": "Αποθήκευση…",
"cancel": "Ακύρωση",
"close": "Κλείσιμο",
"copy": "Αντιγραφή",
"back": "Πίσω",
"pictureInPicture": "Εικόνα σε εικόνα",
"cameraAudio": "Ήχος κάμερας",
"edit": "Επεξεργασία",
"copyCoordinates": "Αντιγραφή συντεταγμένων",
"delete": "Διαγραφή",
"yes": "Ναι",
"no": "Όχι",
"download": "Κατέβασμα",
"info": "Πληροφορίες"
},
"unit": {
"speed": {
"mph": "mph",
"kph": "χλμ/ώρα"
},
"length": {
"meters": "μέτρα"
},
"data": {
"kbps": "kB/s",
"mbps": "MB/s",
"gbps": "GB/s",
"kbph": "kB/ώρα",
"mbph": "MB/ώρα",
"gbph": "GB/ώρα"
}
},
"label": {
"back": "Επιστροφή"
} }
} }

View File

@ -62,5 +62,8 @@
"audioDetect": { "audioDetect": {
"enable": "Ενεργοποίηση Ανίχνευσης Ήχου", "enable": "Ενεργοποίηση Ανίχνευσης Ήχου",
"disable": "Απενεργοποίηση Ανίχνευσης Ήχου" "disable": "Απενεργοποίηση Ανίχνευσης Ήχου"
},
"noCameras": {
"buttonText": "Προσθήκη Κάμερας"
} }
} }

View File

@ -42,5 +42,15 @@
"cameraSetting": { "cameraSetting": {
"camera": "Κάμερα", "camera": "Κάμερα",
"noCamera": "Δεν υπάρχει Κάμερα" "noCamera": "Δεν υπάρχει Κάμερα"
},
"triggers": {
"dialog": {
"form": {
"friendly_name": {
"placeholder": "Ονομάτισε ή περιέγραψε αυτό το εύνασμα",
"description": "Ένα προαιρετικό φιλικό όνομα, ή ένα περιγραφικό κείμενο για αυτό το εύνασμα."
}
}
}
} }
} }

View File

@ -3,6 +3,7 @@
"user": "Username", "user": "Username",
"password": "Password", "password": "Password",
"login": "Login", "login": "Login",
"firstTimeLogin": "Trying to log in for the first time? Credentials are printed in the Frigate logs.",
"errors": { "errors": {
"usernameRequired": "Username is required", "usernameRequired": "Username is required",
"passwordRequired": "Password is required", "passwordRequired": "Password is required",

View File

@ -23,7 +23,7 @@
"label": "Min face recognitions for the sub label to be applied to the person object." "label": "Min face recognitions for the sub label to be applied to the person object."
}, },
"save_attempts": { "save_attempts": {
"label": "Number of face attempts to save in the train tab." "label": "Number of face attempts to save in the recent recognitions tab."
}, },
"blur_confidence_filter": { "blur_confidence_filter": {
"label": "Apply blur quality filter to face confidence." "label": "Apply blur quality filter to face confidence."

View File

@ -1,4 +1,5 @@
{ {
"documentTitle": "Classification Models",
"button": { "button": {
"deleteClassificationAttempts": "Delete Classification Images", "deleteClassificationAttempts": "Delete Classification Images",
"renameCategory": "Rename Class", "renameCategory": "Rename Class",
@ -41,13 +42,94 @@
"invalidName": "Invalid name. Names can only include letters, numbers, spaces, apostrophes, underscores, and hyphens." "invalidName": "Invalid name. Names can only include letters, numbers, spaces, apostrophes, underscores, and hyphens."
}, },
"train": { "train": {
"title": "Train", "title": "Recent Classifications",
"aria": "Select Train" "aria": "Select Recent Classifications"
}, },
"categories": "Classes", "categories": "Classes",
"createCategory": { "createCategory": {
"new": "Create New Class" "new": "Create New Class"
}, },
"categorizeImageAs": "Classify Image As:", "categorizeImageAs": "Classify Image As:",
"categorizeImage": "Classify Image" "categorizeImage": "Classify Image",
"noModels": {
"object": {
"title": "No Object Classification Models",
"description": "Create a custom model to classify detected objects.",
"buttonText": "Create Object Model"
},
"state": {
"title": "No State Classification Models",
"description": "Create a custom model to monitor and classify state changes in specific camera areas.",
"buttonText": "Create State Model"
}
},
"wizard": {
"title": "Create New Classification",
"steps": {
"nameAndDefine": "Name & Define",
"stateArea": "State Area",
"chooseExamples": "Choose Examples"
},
"step1": {
"description": "State models monitor fixed camera areas for changes (e.g., door open/closed). Object models add classifications to detected objects (e.g., known animals, delivery persons, etc.).",
"name": "Name",
"namePlaceholder": "Enter model name...",
"type": "Type",
"typeState": "State",
"typeObject": "Object",
"objectLabel": "Object Label",
"objectLabelPlaceholder": "Select object type...",
"classificationType": "Classification Type",
"classificationTypeTip": "Learn about classification types",
"classificationTypeDesc": "Sub Labels add additional text to the object label (e.g., 'Person: UPS'). Attributes are searchable metadata stored separately in the object metadata.",
"classificationSubLabel": "Sub Label",
"classificationAttribute": "Attribute",
"classes": "Classes",
"classesTip": "Learn about classes",
"classesStateDesc": "Define the different states your camera area can be in. For example: 'open' and 'closed' for a garage door.",
"classesObjectDesc": "Define the different categories to classify detected objects into. For example: 'delivery_person', 'resident', 'stranger' for person classification.",
"classPlaceholder": "Enter class name...",
"errors": {
"nameRequired": "Model name is required",
"nameLength": "Model name must be 64 characters or less",
"nameOnlyNumbers": "Model name cannot contain only numbers",
"classRequired": "At least 1 class is required",
"classesUnique": "Class names must be unique",
"stateRequiresTwoClasses": "State models require at least 2 classes",
"objectLabelRequired": "Please select an object label",
"objectTypeRequired": "Please select a classification type"
}
},
"step2": {
"description": "Select cameras and define the area to monitor for each camera. The model will classify the state of these areas.",
"cameras": "Cameras",
"selectCamera": "Select Camera",
"noCameras": "Click + to add cameras",
"selectCameraPrompt": "Select a camera from the list to define its monitoring area"
},
"step3": {
"selectImagesPrompt": "Select all images with: {{className}}",
"selectImagesDescription": "Click on images to select them. Click Continue when you're done with this class.",
"generating": {
"title": "Generating Sample Images",
"description": "Frigate is pulling representative images from your recordings. This may take a moment..."
},
"training": {
"title": "Training Model",
"description": "Your model is being trained in the background. Close this dialog, and your model will start running as soon as training is complete."
},
"retryGenerate": "Retry Generation",
"noImages": "No sample images generated",
"classifying": "Classifying & Training...",
"trainingStarted": "Training started successfully",
"errors": {
"noCameras": "No cameras configured",
"noObjectLabel": "No object label selected",
"generateFailed": "Failed to generate examples: {{error}}",
"generationFailed": "Generation failed. Please try again.",
"classifyFailed": "Failed to classify images: {{error}}"
},
"generateSuccess": "Successfully generated sample images"
}
}
} }

View File

@ -19,10 +19,11 @@
"noFoundForTimePeriod": "No events found for this time period." "noFoundForTimePeriod": "No events found for this time period."
}, },
"detail": { "detail": {
"label": "Detail",
"noDataFound": "No detail data to review", "noDataFound": "No detail data to review",
"aria": "Toggle detail view", "aria": "Toggle detail view",
"trackedObject_one": "tracked object", "trackedObject_one": "object",
"trackedObject_other": "tracked objects", "trackedObject_other": "objects",
"noObjectDetailData": "No object detail data available." "noObjectDetailData": "No object detail data available."
}, },
"objectTrack": { "objectTrack": {

View File

@ -194,6 +194,12 @@
}, },
"deleteTrackedObject": { "deleteTrackedObject": {
"label": "Delete this tracked object" "label": "Delete this tracked object"
},
"showObjectDetails": {
"label": "Show object path"
},
"hideObjectDetails": {
"label": "Hide object path"
} }
}, },
"dialog": { "dialog": {

View File

@ -5,10 +5,6 @@
"invalidName": "Invalid name. Names can only include letters, numbers, spaces, apostrophes, underscores, and hyphens." "invalidName": "Invalid name. Names can only include letters, numbers, spaces, apostrophes, underscores, and hyphens."
}, },
"details": { "details": {
"subLabelScore": "Sub Label Score",
"scoreInfo": "The sub label score is the weighted score for all of the recognized face confidences, so this may differ from the score shown on the snapshot.",
"face": "Face Details",
"faceDesc": "Details of the tracked object that generated this face",
"timestamp": "Timestamp", "timestamp": "Timestamp",
"unknown": "Unknown" "unknown": "Unknown"
}, },
@ -19,10 +15,8 @@
}, },
"collections": "Collections", "collections": "Collections",
"createFaceLibrary": { "createFaceLibrary": {
"title": "Create Collection",
"desc": "Create a new collection",
"new": "Create New Face", "new": "Create New Face",
"nextSteps": "To build a strong foundation:<li>Use the Train tab to select and train on images for each detected person.</li><li>Focus on straight-on images for best results; avoid training images that capture faces at an angle.</li></ul>" "nextSteps": "To build a strong foundation:<li>Use the Recent Recognitions tab to select and train on images for each detected person.</li><li>Focus on straight-on images for best results; avoid training images that capture faces at an angle.</li></ul>"
}, },
"steps": { "steps": {
"faceName": "Enter Face Name", "faceName": "Enter Face Name",
@ -33,12 +27,10 @@
} }
}, },
"train": { "train": {
"title": "Train", "title": "Recent Recognitions",
"aria": "Select train", "aria": "Select recent recognitions",
"empty": "There are no recent face recognition attempts" "empty": "There are no recent face recognition attempts"
}, },
"selectItem": "Select {{item}}",
"selectFace": "Select Face",
"deleteFaceLibrary": { "deleteFaceLibrary": {
"title": "Delete Name", "title": "Delete Name",
"desc": "Are you sure you want to delete the collection {{name}}? This will permanently delete all associated faces." "desc": "Are you sure you want to delete the collection {{name}}? This will permanently delete all associated faces."
@ -69,7 +61,6 @@
"maxSize": "Max size: {{size}}MB" "maxSize": "Max size: {{size}}MB"
}, },
"nofaces": "No faces available", "nofaces": "No faces available",
"pixels": "{{area}}px",
"trainFaceAs": "Train Face as:", "trainFaceAs": "Train Face as:",
"trainFace": "Train Face", "trainFace": "Train Face",
"toast": { "toast": {

View File

@ -188,6 +188,10 @@
"testSuccess": "Connection test successful!", "testSuccess": "Connection test successful!",
"testFailed": "Connection test failed. Please check your input and try again.", "testFailed": "Connection test failed. Please check your input and try again.",
"streamDetails": "Stream Details", "streamDetails": "Stream Details",
"testing": {
"probingMetadata": "Probing camera metadata...",
"fetchingSnapshot": "Fetching camera snapshot..."
},
"warnings": { "warnings": {
"noSnapshot": "Unable to fetch a snapshot from the configured stream." "noSnapshot": "Unable to fetch a snapshot from the configured stream."
}, },
@ -197,8 +201,9 @@
"nameLength": "Camera name must be 64 characters or less", "nameLength": "Camera name must be 64 characters or less",
"invalidCharacters": "Camera name contains invalid characters", "invalidCharacters": "Camera name contains invalid characters",
"nameExists": "Camera name already exists", "nameExists": "Camera name already exists",
"customUrlRtspRequired": "Custom URLs must begin with \"rtsp://\". Manual configuration is required for non-RTSP camera streams.",
"brands": { "brands": {
"reolink-rtsp": "Reolink RTSP is not recommended. It is recommended to enable http in the camera settings and restart the camera wizard." "reolink-rtsp": "Reolink RTSP is not recommended. Enable HTTP in the camera's firmware settings and restart the wizard."
} }
}, },
"docs": { "docs": {
@ -272,6 +277,8 @@
"title": "Stream Validation", "title": "Stream Validation",
"videoCodecGood": "Video codec is {{codec}}.", "videoCodecGood": "Video codec is {{codec}}.",
"audioCodecGood": "Audio codec is {{codec}}.", "audioCodecGood": "Audio codec is {{codec}}.",
"resolutionHigh": "A resolution of {{resolution}} may cause increased resource usage.",
"resolutionLow": "A resolution of {{resolution}} may be too low for reliable detection of small objects.",
"noAudioWarning": "No audio detected for this stream, recordings will not have audio.", "noAudioWarning": "No audio detected for this stream, recordings will not have audio.",
"audioCodecRecordError": "The AAC audio codec is required to support audio in recordings.", "audioCodecRecordError": "The AAC audio codec is required to support audio in recordings.",
"audioCodecRequired": "An audio stream is required to support audio detection.", "audioCodecRequired": "An audio stream is required to support audio detection.",

View File

@ -280,5 +280,8 @@
"desc": "Página no encontrada" "desc": "Página no encontrada"
}, },
"selectItem": "Seleccionar {{item}}", "selectItem": "Seleccionar {{item}}",
"readTheDocumentation": "Leer la documentación" "readTheDocumentation": "Leer la documentación",
"information": {
"pixels": "{{area}}px"
}
} }

View File

@ -120,7 +120,8 @@
"button": { "button": {
"export": "Exportar", "export": "Exportar",
"markAsReviewed": "Marcar como revisado", "markAsReviewed": "Marcar como revisado",
"deleteNow": "Eliminar ahora" "deleteNow": "Eliminar ahora",
"markAsUnreviewed": "Marcar como no revisado"
} }
}, },
"imagePicker": { "imagePicker": {

View File

@ -49,7 +49,7 @@
"selectImage": "Por favor, selecciona un archivo de imagen." "selectImage": "Por favor, selecciona un archivo de imagen."
}, },
"dropActive": "Suelta la imagen aquí…", "dropActive": "Suelta la imagen aquí…",
"dropInstructions": "Arrastra y suelta una imagen aquí, o haz clic para seleccionar", "dropInstructions": "Arrastra y suelta, o pega una imagen aquí, o haz clic para seleccionar",
"maxSize": "Tamaño máximo: {{size}}MB" "maxSize": "Tamaño máximo: {{size}}MB"
}, },
"toast": { "toast": {

View File

@ -147,7 +147,7 @@
"snapshots": "Capturas de pantalla", "snapshots": "Capturas de pantalla",
"autotracking": "Seguimiento automático", "autotracking": "Seguimiento automático",
"cameraEnabled": "Cámara habilitada", "cameraEnabled": "Cámara habilitada",
"transcription": "Transcripción de audio" "transcription": "Transcripción de Audio"
}, },
"history": { "history": {
"label": "Mostrar grabaciones históricas" "label": "Mostrar grabaciones históricas"
@ -170,5 +170,10 @@
"transcription": { "transcription": {
"enable": "Habilitar transcripción de audio en tiempo real", "enable": "Habilitar transcripción de audio en tiempo real",
"disable": "Deshabilitar transcripción de audio en tiempo real" "disable": "Deshabilitar transcripción de audio en tiempo real"
},
"noCameras": {
"title": "No hay cámaras configuradas",
"description": "Comienza conectando una cámara.",
"buttonText": "Añade Cámara"
} }
} }

View File

@ -23,7 +23,8 @@
"users": "Usuarios", "users": "Usuarios",
"notifications": "Notificaciones", "notifications": "Notificaciones",
"enrichments": "Análisis avanzado", "enrichments": "Análisis avanzado",
"triggers": "Disparadores" "triggers": "Disparadores",
"roles": "Rols"
}, },
"dialog": { "dialog": {
"unsavedChanges": { "unsavedChanges": {
@ -773,7 +774,71 @@
"desc": "Editar configuractión del disparador para cámara {{camera}}" "desc": "Editar configuractión del disparador para cámara {{camera}}"
}, },
"deleteTrigger": { "deleteTrigger": {
"title": "Eliminar Disparador" "title": "Eliminar Disparador",
"desc": "Está seguro de que desea eliminar el disparador <strong>{{triggerName}}</strong>? Esta acción no se puede deshacer."
},
"form": {
"name": {
"title": "Nombre",
"placeholder": "Entre nombre de disparador",
"error": {
"minLength": "El nombre debe tener al menos 2 caracteres.",
"invalidCharacters": "El nombre sólo puede contener letras, números, guiones bajos, y guiones.",
"alreadyExists": "Un disparador con este nombre ya existe para esta cámara."
}
},
"enabled": {
"description": "Activa o desactiva este disparador"
},
"type": {
"title": "Tipo",
"placeholder": "Seleccione tipo de disparador"
},
"friendly_name": {
"title": "Nombre amigable",
"placeholder": "Nombre o describa este disparador",
"description": "Un nombre o texto descriptivo amigable (opcional) para este disparador."
},
"content": {
"title": "Contenido",
"imagePlaceholder": "Seleccione una imágen",
"textPlaceholder": "Entre contenido de texto",
"error": {
"required": "El contenido es requrido."
},
"imageDesc": "Seleccione una imágen para iniciar esta acción cuando una imágen similar es detectada.",
"textDesc": "Entre texto para iniciar esta acción cuando la descripción de un objecto seguido similar es detectado."
},
"threshold": {
"title": "Umbral",
"error": {
"min": "El umbral debe ser al menos 0",
"max": "El umbral debe ser al menos 1"
}
},
"actions": {
"title": "Acciones",
"error": {
"min": "Al menos una acción debe ser seleccionada."
},
"desc": "Por defecto, Frigate manda un mensaje MQTT por todos los disparadores. Seleccione una acción adicional que se realizará cuando este disparador se accione."
}
}
},
"semanticSearch": {
"title": "Búsqueda semántica desactivada",
"desc": "Búsqueda semántica debe estar activada para usar Disparadores."
},
"toast": {
"success": {
"createTrigger": "Disparador {{name}} creado exitosamente.",
"updateTrigger": "Disparador {{name}} actualizado exitosamente.",
"deleteTrigger": "Disparador {{name}} eliminado exitosamente."
},
"error": {
"createTriggerFailed": "Fallo al crear el disparador: {{errorMessage}}",
"updateTriggerFailed": "Fallo al actualizar el disparador: {{errorMessage}}",
"deleteTriggerFailed": "Fallo al eliminar el disparador: {{errorMessage}}"
} }
} }
}, },

View File

@ -105,7 +105,7 @@
"unusedStorageInformation": "Información de Almacenamiento No Utilizado" "unusedStorageInformation": "Información de Almacenamiento No Utilizado"
}, },
"shm": { "shm": {
"title": "Asignación SHM (memoria compartida)", "title": "Asignación de SHM (memoria compartida)",
"warning": "El tamaño actual de SHM de {{total}}MB es muy pequeño. Aumente al menos a {{min_shm}}MB." "warning": "El tamaño actual de SHM de {{total}}MB es muy pequeño. Aumente al menos a {{min_shm}}MB."
} }
}, },

View File

@ -425,5 +425,67 @@
"fowl": "Volaille", "fowl": "Volaille",
"cluck": "Gloussement", "cluck": "Gloussement",
"cock_a_doodle_doo": "Cocorico", "cock_a_doodle_doo": "Cocorico",
"gobble": "Glouglou" "gobble": "Glouglou",
"chird": "Accord",
"change_ringing": "Changer la sonnerie",
"sodeling": "Sodèle",
"shofar": "Choffar",
"liquid": "Liquide",
"splash": "Éclabousser",
"slosh": "Patauger",
"squish": "Gargouillis",
"drip": "Goutte",
"trickle": "Filet",
"gush": "Jet",
"fill": "Remplir",
"spray": "Pulvérisation",
"pump": "Pompe",
"stir": "Remuer",
"boiling": "Ébullition",
"arrow": "Flèche",
"pour": "Verser",
"sonar": "Sonar",
"whoosh": "Whoosh",
"thump": "Cogner",
"thunk": "Je pense",
"electronic_tuner": "Accordeur électronique",
"effects_unit": "Unité d'effets",
"chorus_effect": "Effet de chœur",
"basketball_bounce": "Rebond de basket-ball",
"bang": "Claquer",
"slap": "Gifler",
"whack": "Battre",
"smash": "Fracasser",
"breaking": "Rupture",
"bouncing": "Rebondir",
"whip": "Fouet",
"flap": "Rabat",
"scratch": "Gratter",
"scrape": "Gratter",
"rub": "Frotter",
"roll": "Rouler",
"crushing": "Écrasement",
"crumpling": "Froissement",
"tearing": "Déchirure",
"beep": "Bip",
"ping": "Ping",
"ding": "Ding",
"clang": "Bruit",
"squeal": "Hurler",
"creak": "Craquer",
"rustle": "Bruissement",
"whir": "Vrombissement",
"clatter": "Bruit",
"sizzle": "Grésiller",
"clicking": "En cliquant",
"clickety_clack": "Clic-clac",
"rumble": "Gronder",
"plop": "Ploc",
"hum": "Hum",
"harmonic": "Harmonique",
"outside": "Extérieur",
"reverberation": "Réverbération",
"echo": "Echo",
"distortion": "Distorsion",
"vibration": "Vibration"
} }

View File

@ -279,6 +279,17 @@
"length": { "length": {
"feet": "pieds", "feet": "pieds",
"meters": "mètres" "meters": "mètres"
},
"data": {
"kbps": "ko/s",
"mbps": "Mo/s",
"gbps": "Go/s",
"kbph": "ko/heure",
"mbph": "Mo/heure",
"gbph": "Go/heure"
} }
},
"information": {
"pixels": "{{area}}px"
} }
} }

View File

@ -120,7 +120,8 @@
"button": { "button": {
"export": "Exporter", "export": "Exporter",
"markAsReviewed": "Marquer comme passé en revue", "markAsReviewed": "Marquer comme passé en revue",
"deleteNow": "Supprimer maintenant" "deleteNow": "Supprimer maintenant",
"markAsUnreviewed": "Marqué comme non passé en revue"
} }
}, },
"imagePicker": { "imagePicker": {

View File

@ -46,7 +46,7 @@
}, },
"imageEntry": { "imageEntry": {
"dropActive": "Déposez l'image ici…", "dropActive": "Déposez l'image ici…",
"dropInstructions": "Glissez et déposez une image ici, ou cliquez pour sélectionner", "dropInstructions": "Glissez-déposez ou coller une image ici, ou cliquez pour la sélectionner",
"maxSize": "Taille max : {{size}}Mo", "maxSize": "Taille max : {{size}}Mo",
"validation": { "validation": {
"selectImage": "Veuillez sélectionner un fichier image." "selectImage": "Veuillez sélectionner un fichier image."

View File

@ -94,8 +94,8 @@
"failedToEnd": "Impossible de terminer l'enregistrement manuel à la demande.", "failedToEnd": "Impossible de terminer l'enregistrement manuel à la demande.",
"started": "Enregistrement à la demande démarré.", "started": "Enregistrement à la demande démarré.",
"recordDisabledTips": "Puisque l'enregistrement est désactivé ou restreint dans la configuration de cette caméra, seul un instantané sera enregistré.", "recordDisabledTips": "Puisque l'enregistrement est désactivé ou restreint dans la configuration de cette caméra, seul un instantané sera enregistré.",
"title": "Enregistrement à la demande", "title": "À la demande",
"tips": "Démarrez un événement manuel en fonction des paramètres de conservation d'enregistrement de cette caméra." "tips": "Téléchargez un instantané immédiat ou démarrez un événement manuel en fonction des paramètres de conservation d'enregistrement de cette caméra."
}, },
"streamingSettings": "Paramètres de streaming", "streamingSettings": "Paramètres de streaming",
"notifications": "Notifications", "notifications": "Notifications",
@ -170,5 +170,16 @@
"transcription": { "transcription": {
"enable": "Activer la transcription audio en direct", "enable": "Activer la transcription audio en direct",
"disable": "Désactiver la transcription audio en direct" "disable": "Désactiver la transcription audio en direct"
},
"noCameras": {
"title": "Aucune caméra configurée",
"description": "Pour commencer, connectez une caméra.",
"buttonText": "Ajouter une caméra"
},
"snapshot": {
"takeSnapshot": "Télécharger un instantané immédiat",
"noVideoSource": "Aucune source disponible pour un instantané.",
"captureFailed": "Échec de la capture d'instantané.",
"downloadStarted": "Démarrage du téléchargement de l'instantané."
} }
} }

View File

@ -10,7 +10,9 @@
"object": "Débogage - Frigate", "object": "Débogage - Frigate",
"frigatePlus": "Paramètres Frigate+ - Frigate", "frigatePlus": "Paramètres Frigate+ - Frigate",
"notifications": "Paramètres de notification - Frigate", "notifications": "Paramètres de notification - Frigate",
"enrichments": "Paramètres d'enrichissements - Frigate" "enrichments": "Paramètres d'enrichissements - Frigate",
"cameraManagement": "Gestion des caméras - Frigate",
"cameraReview": "Paramètres de revue des caméras - Frigate"
}, },
"menu": { "menu": {
"ui": "Interface utilisateur", "ui": "Interface utilisateur",
@ -23,7 +25,10 @@
"notifications": "Notifications", "notifications": "Notifications",
"frigateplus": "Frigate+", "frigateplus": "Frigate+",
"enrichments": "Enrichissements", "enrichments": "Enrichissements",
"triggers": "Déclencheurs" "triggers": "Déclencheurs",
"roles": "Rôles",
"cameraManagement": "Gestion",
"cameraReview": "Revue"
}, },
"dialog": { "dialog": {
"unsavedChanges": { "unsavedChanges": {
@ -816,6 +821,11 @@
"error": { "error": {
"min": "Au moins une action doit être sélectionnée." "min": "Au moins une action doit être sélectionnée."
} }
},
"friendly_name": {
"title": "Nom convivial",
"placeholder": "Nommez ou décrivez ce déclencheur",
"description": "Nom convivial ou texte descriptif facultatif pour ce déclencheur."
} }
} }
}, },
@ -830,6 +840,10 @@
"updateTriggerFailed": "Échec de la mise à jour du déclencheur : {{errorMessage}}", "updateTriggerFailed": "Échec de la mise à jour du déclencheur : {{errorMessage}}",
"deleteTriggerFailed": "Échec de la suppression du déclencheur : {{errorMessage}}" "deleteTriggerFailed": "Échec de la suppression du déclencheur : {{errorMessage}}"
} }
},
"semanticSearch": {
"title": "La recherche sémantique est désactivée",
"desc": "La recherche sémantique doit être activée pour utiliser les déclencheurs."
} }
}, },
"roles": { "roles": {
@ -891,5 +905,222 @@
} }
} }
} }
},
"cameraWizard": {
"title": "Ajouter une caméra",
"description": "Suivez les étapes ci-dessous pour ajouter une nouvelle caméra à votre installation Frigate.",
"steps": {
"nameAndConnection": "Nom et connexion",
"streamConfiguration": "Configuration du flux",
"validationAndTesting": "Validation et tests"
},
"save": {
"success": "Réussite de l'enregistrement de la nouvelle caméra {{cameraName}}.",
"failure": "Échec lors de l'enregistrement de {{cameraName}}."
},
"testResultLabels": {
"resolution": "Résolution",
"video": "Vidéo",
"audio": "Audio",
"fps": "FPS"
},
"commonErrors": {
"noUrl": "Saisissez une URL de flux valide s'il vous plait",
"testFailed": "Échec du test de flux : {{error}}"
},
"step1": {
"description": "Saisissez les détails de votre caméra et testez la connexion.",
"cameraName": "Nom de la caméra",
"cameraNamePlaceholder": "par exemple, porte-entree ou Apercu Arriere_Cour",
"host": "Hôte / Adresse IP",
"port": "Port",
"username": "Nom d'utilisateur",
"usernamePlaceholder": "Facultatif",
"password": "Mot de passe",
"passwordPlaceholder": "Facultatif",
"selectTransport": "Sélectionnez le protocole de transport",
"cameraBrand": "Marque de la caméra",
"selectBrand": "Sélectionnez la marque de la caméra pour le modèle de l'URL",
"customUrl": "URL de flux personnalisé",
"brandInformation": "Information sur la marque",
"brandUrlFormat": "Pour les caméras avec un format d'URL RTSP comme : {{exampleUrl}}",
"customUrlPlaceholder": "rtsp://nomutilisateur:motdepasse@hote:port/chemin",
"testConnection": "Tester la connexion",
"testSuccess": "Test de connexion réussi!",
"testFailed": "Échec du test de connexion. Veuillez vérifier votre saisie et réessayer.",
"streamDetails": "Détails du flux",
"warnings": {
"noSnapshot": "Impossible de récupérer un instantané à partir du flux configuré."
},
"errors": {
"brandOrCustomUrlRequired": "Sélectionnez une marque de caméra avec hôte/IP ou choisissez « Autre » avec une URL personnalisée",
"nameRequired": "Le nom de la caméra est requis",
"nameLength": "Le nom de la caméra doit comporter 64 caractères ou moins",
"invalidCharacters": "Le nom de la caméra contient des caractères non valides",
"nameExists": "Le nom de la caméra existe déjà",
"brands": {
"reolink-rtsp": "Reolink RTSP n'est pas recommandé. Il est recommandé d'activer le protocole HTTP dans les paramètres de la caméra et de redémarrer l'assistant."
}
},
"docs": {
"reolink": "https://docs.frigate.video/configuration/camera_specific.html#reolink-cameras"
}
},
"step2": {
"description": "Configurez les rôles du flux et ajoutez des flux supplémentaires pour votre caméra.",
"streamsTitle": "Flux de caméra",
"addStream": "Ajouter un flux",
"addAnotherStream": "Ajouter un autre flux",
"streamTitle": "Flux {{number}}",
"streamUrl": "URL du flux",
"streamUrlPlaceholder": "rtsp://username:password@host:port/path",
"url": "URL",
"resolution": "Résolution",
"selectResolution": "Sélectionnez la résolution",
"quality": "Qualité",
"selectQuality": "Sélectionnez la qualité",
"roles": "Rôles",
"roleLabels": {
"record": "Enregistrement",
"audio": "Audio",
"detect": "Détection d'objet"
},
"testStream": "Tester la connexion",
"testSuccess": "Test de diffusion réussi!",
"testFailed": "Le test du flux a échoué",
"testFailedTitle": "Échec du test",
"connected": "Connecté",
"notConnected": "Non connecté",
"featuresTitle": "Caractéristiques",
"go2rtc": "Réduire les connexions à la caméra",
"detectRoleWarning": "Au moins un flux doit avoir le rôle « détecter » pour continuer.",
"rolesPopover": {
"title": "Rôles du flux",
"detect": "Flux principal pour la détection d'objets.",
"record": "Enregistre des segments du flux vidéo en fonction des paramètres de configuration.",
"audio": "Flux pour la détection basée sur l'audio."
},
"featuresPopover": {
"title": "Fonctionnalités du flux",
"description": "Utilisez le flux go2rtc pour réduire le nombre de connexions à votre caméra."
}
},
"step3": {
"description": "Validation finale et analyse avant d'enregistrer votre nouvelle caméra. Connectez chaque flux avant d'enregistrer.",
"validationTitle": "Validation du flux",
"connectAllStreams": "Connecter tous les flux",
"reconnectionSuccess": "Reconnexion réussie.",
"reconnectionPartial": "Certains flux n'ont pas pu se reconnecter.",
"streamUnavailable": "Aperçu du flux indisponible",
"reload": "Recharger",
"connecting": "Connexion...",
"streamTitle": "Flux {{number}}",
"failed": "Échoué",
"notTested": "Non testé",
"connectStream": "Connecter",
"connectingStream": "Connexion",
"disconnectStream": "Déconnecter",
"estimatedBandwidth": "Bande passante estimée",
"roles": "Rôles",
"none": "Aucun",
"error": "Erreur",
"streamValidated": "Flux {{number}} validé avec succès",
"streamValidationFailed": "La validation du flux {{number}} a échoué",
"saveAndApply": "Enregistrer une nouvelle caméra",
"saveError": "Configuration invalide. Veuillez vérifier vos paramètres.",
"issues": {
"title": "Validation du flux",
"videoCodecGood": "Le codec vidéo est {{codec}}.",
"audioCodecGood": "Le codec audio est {{codec}}.",
"noAudioWarning": "Aucun audio détecté pour ce flux, les enregistrements n'auront pas d'audio.",
"audioCodecRecordError": "Le codec audio AAC est requis pour prendre en charge l'audio dans les enregistrements.",
"audioCodecRequired": "Un flux audio est requis pour prendre en charge la détection audio.",
"restreamingWarning": "La réduction des connexions à la caméra pour le flux d'enregistrement peut augmenter légèrement l'utilisation du processeur.",
"dahua": {
"substreamWarning": "Le sous-flux 1 est verrouillé en basse résolution. De nombreuses caméras Dahua / Amcrest / EmpireTech prennent en charge des sous-flux supplémentaires qui doivent être activés dans les paramètres de la caméra. Il est recommandé de vérifier et d'utiliser ces flux s'ils sont disponibles."
},
"hikvision": {
"substreamWarning": "Le sous-flux 1 est verrouillé en basse résolution. De nombreuses caméras Hikvision prennent en charge des sous-flux supplémentaires qui doivent être activés dans les paramètres de la caméra. Il est recommandé de vérifier et d'utiliser ces flux s'ils sont disponibles."
}
},
"valid": "Validation"
}
},
"cameraManagement": {
"title": "Gérer les caméras",
"addCamera": "Ajouter une nouvelle caméra",
"editCamera": "Modifier la caméra:",
"selectCamera": "Sélectionnez une caméra",
"backToSettings": "Retour aux paramètres de la caméra",
"streams": {
"title": "Activer/Désactiver les caméras",
"desc": "Désactivez temporairement une caméra jusqu'au redémarrage de Frigate. La désactivation d'une caméra interrompt complètement le traitement des flux de cette caméra par Frigate. La détection, l'enregistrement et le débogage seront indisponibles.<br /><em>Remarque : Ceci ne désactive pas les rediffusions go2rtc.</em>"
},
"cameraConfig": {
"add": "Ajouter une caméra",
"edit": "Modifier la caméra",
"description": "Configurez les paramètres de la caméra, y compris les entrées de flux et les rôles.",
"name": "Nom de la caméra",
"nameRequired": "Le nom de la caméra est requis",
"nameLength": "Le nom de la caméra doit comporter moins de 64 caractères.",
"namePlaceholder": "par exemple, porte d'entrée ou aperçu de la cour arrière",
"enabled": "Activé",
"ffmpeg": {
"inputs": "Flux d'entrée",
"path": "Chemin du flux",
"pathRequired": "Le chemin du flux est requis",
"pathPlaceholder": "rtsp://...",
"roles": "Rôles",
"rolesRequired": "Au moins un rôle est requis",
"rolesUnique": "Chaque rôle (audio, détection, enregistrement) ne peut être attribué qu'à un seul flux",
"addInput": "Ajouter un flux d'entrée",
"removeInput": "Supprimer le flux d'entrée",
"inputsRequired": "Au moins un flux d'entrée est requis"
},
"go2rtcStreams": "Flux go2rtc",
"streamUrls": "URLs des flux",
"addUrl": "Ajouter une URL",
"addGo2rtcStream": "Ajouter un flux go2rtc",
"toast": {
"success": "La caméra {{cameraName}} a été enregistrée avec succès"
}
}
},
"cameraReview": {
"title": "Paramètres d'examen de la caméra",
"object_descriptions": {
"title": "Descriptions d'objets IA génératives",
"desc": "Activez/désactivez temporairement les descriptions d'objets générées par l'IA pour cette caméra. Si elles sont désactivées, les descriptions générées par l'IA ne seront pas demandées pour les objets suivis par cette caméra."
},
"review_descriptions": {
"title": "Descriptions des évaluations de l'IA générative",
"desc": "Activez/désactivez temporairement les descriptions d'évaluation génératrices par l'IA pour cette caméra. Si elles sont désactivées, les descriptions générées par l'IA ne seront pas demandées pour les éléments d'évaluation de cette caméra."
},
"review": {
"title": "Revoir",
"desc": "Activez/désactivez temporairement les alertes et les détections pour cette caméra jusqu'au redémarrage de Frigate. Une fois désactivée, aucun nouvel élément d'analyse ne sera généré. ",
"alerts": "Alertes. ",
"detections": "Détections. "
},
"reviewClassification": {
"title": "Classement des avis",
"desc": "Frigate catégorise les éléments d'évaluation en alertes et détections. Par défaut, tous les objets <em>personne</em> et <em>voiture</em> sont considérés comme des alertes. Vous pouvez affiner la catégorisation de vos éléments d'évaluation en configurant les zones requises.",
"noDefinedZones": "Aucune zone n'est définie pour cette caméra.",
"objectAlertsTips": "Tous les objets {{alertsLabels}} sur {{cameraName}} seront affichés sous forme d'alertes.",
"zoneObjectAlertsTips": "Tous les objets {{alertsLabels}} détectés dans {{zone}} sur {{cameraName}} seront affichés sous forme d'alertes.",
"objectDetectionsTips": "Tous les objets {{detectionsLabels}} non classés sur {{cameraName}} seront affichés comme détections, quelle que soit la zone dans laquelle ils se trouvent.",
"zoneObjectDetectionsTips": {
"text": "Tous les objets {{detectionsLabels}} non classés dans {{zone}} sur {{cameraName}} seront affichés comme détections.",
"notSelectDetections": "Tous les objets {{detectionsLabels}} détectés dans {{zone}} sur {{cameraName}} non classés comme alertes seront affichés comme détections, quelle que soit la zone dans laquelle ils se trouvent.",
"regardlessOfZoneObjectDetectionsTips": "Tous les objets {{detectionsLabels}} non classés sur {{cameraName}} seront affichés comme détections, quelle que soit la zone dans laquelle ils se trouvent."
},
"unsavedChanges": "Paramètres de classification des avis non enregistrés pour {{camera}}",
"selectAlertsZones": "Sélectionnez les zones pour les alertes",
"selectDetectionsZones": "Sélectionner les zones pour les détections",
"limitDetections": "Limiter les détections à des zones spécifiques",
"toast": {
"success": "La configuration de la classification a été enregistrée. Redémarrez Frigate pour appliquer les modifications."
}
}
} }
} }

View File

@ -18,7 +18,7 @@
"humming": "זמזום", "humming": "זמזום",
"groan": "אנקה", "groan": "אנקה",
"grunt": "לנחור", "grunt": "לנחור",
"whistling": "שריקה", "whistling": "לשרוק",
"breathing": "נשימה", "breathing": "נשימה",
"wheeze": "גניחה", "wheeze": "גניחה",
"snoring": "נחירה", "snoring": "נחירה",
@ -69,7 +69,7 @@
"fly": "זבוב", "fly": "זבוב",
"buzz": "זמזם.", "buzz": "זמזם.",
"frog": "צפרדע", "frog": "צפרדע",
"croak": רקור.", "croak": ִרקוּר",
"snake": "נחש", "snake": "נחש",
"rattle": "טרטור", "rattle": "טרטור",
"whale_vocalization": "קולות לוויתן", "whale_vocalization": "קולות לוויתן",
@ -81,7 +81,7 @@
"bass_guitar": "גיטרה בס", "bass_guitar": "גיטרה בס",
"acoustic_guitar": "גיטרה אקוסטית", "acoustic_guitar": "גיטרה אקוסטית",
"steel_guitar": "גיטרה פלדה", "steel_guitar": "גיטרה פלדה",
"tapping": "הקשה.", "tapping": "להקיש",
"strum": "פריטה", "strum": "פריטה",
"banjo": "בנג'ו", "banjo": "בנג'ו",
"sitar": "סיטאר", "sitar": "סיטאר",
@ -189,7 +189,7 @@
"church_bell": "פעמון כנסיה", "church_bell": "פעמון כנסיה",
"jingle_bell": "ג'ינגל בל", "jingle_bell": "ג'ינגל בל",
"bicycle_bell": "פעמון אופניים", "bicycle_bell": "פעמון אופניים",
"chime": לצול", "chime": ִלצוּל",
"wind_chime": "פעמון רוח", "wind_chime": "פעמון רוח",
"harmonica": "הרמוניקה", "harmonica": "הרמוניקה",
"accordion": "אקורדיון", "accordion": "אקורדיון",
@ -341,7 +341,7 @@
"microwave_oven": "מיקרוגל", "microwave_oven": "מיקרוגל",
"water_tap": "ברז מים", "water_tap": "ברז מים",
"bathtub": "אמבטיה", "bathtub": "אמבטיה",
"dishes": "כלים.", "dishes": "מנות",
"scissors": "מספריים", "scissors": "מספריים",
"toothbrush": "מברשת שיניים", "toothbrush": "מברשת שיניים",
"toilet_flush": "הורדת מים לאסלה", "toilet_flush": "הורדת מים לאסלה",
@ -355,7 +355,7 @@
"computer_keyboard": "מקלדת מחשב", "computer_keyboard": "מקלדת מחשב",
"writing": "כתיבה", "writing": "כתיבה",
"telephone_bell_ringing": "צלצול טלפון", "telephone_bell_ringing": "צלצול טלפון",
"ringtone": "צליל חיוג.", "ringtone": "צלצול",
"clock": "שעון", "clock": "שעון",
"telephone_dialing": "טלפון מחייג", "telephone_dialing": "טלפון מחייג",
"dial_tone": "צליל חיוג", "dial_tone": "צליל חיוג",
@ -425,5 +425,54 @@
"slam": "טריקה", "slam": "טריקה",
"telephone": "טלפון", "telephone": "טלפון",
"tuning_fork": "מזלג כוונון", "tuning_fork": "מזלג כוונון",
"raindrop": "טיפות גשם" "raindrop": "טיפות גשם",
"smash": "רסק",
"boiling": "רותח",
"sonar": "סונר",
"arrow": "חץ",
"whack": "מַהֲלוּמָה",
"sine_wave": "גל סינוס",
"harmonic": "הרמוניה",
"chirp_tone": "צליל ציוץ",
"pulse": "דוֹפֶק",
"inside": "בְּתוֹך",
"outside": "בחוץ",
"reverberation": "הִדהוּד",
"echo": "הד",
"noise": "רעש",
"mains_hum": "זמזום ראשי",
"distortion": "סַלְפָנוּת",
"sidetone": "צליל צדדי",
"cacophony": "קָקוֹפוֹניָה",
"throbbing": "פְּעִימָה",
"vibration": "רֶטֶט",
"sodeling": "מיזוג",
"change_ringing": "שינוי צלצול",
"shofar": "שופר",
"liquid": "נוזל",
"splash": "התזה",
"slosh": "שכשוך",
"squish": "מעיכה",
"drip": "טפטוף",
"pour": "לִשְׁפּוֹך",
"trickle": "לְטַפטֵף",
"gush": "פֶּרֶץ",
"fill": "מילוי",
"spray": "ריסוס",
"pump": "משאבה",
"stir": "בחישה",
"whoosh": "מהיר",
"thump": "חֲבָטָה",
"thunk": "תרועה",
"electronic_tuner": "מכוון אלקטרוני",
"effects_unit": "יחידת אפקטים",
"chorus_effect": "אפקט מקהלה",
"basketball_bounce": "קפיצת כדורסל",
"bang": "לִדפּוֹק",
"slap": "סְטִירָה",
"breaking": "שְׁבִירָה",
"bouncing": "הַקפָּצָה",
"whip": "שׁוֹט",
"flap": "מַדָף",
"scratch": "לְגַרֵד"
} }

View File

@ -1,5 +1,5 @@
{ {
"filter": "לסנן", "filter": "מסנן",
"features": { "features": {
"submittedToFrigatePlus": { "submittedToFrigatePlus": {
"tips": "עליך תחילה לסנן לפי אובייקטים במעקב שיש להם תמונת מצב.<br /><br />לא ניתן לשלוח ל-Frigate+ אובייקטים במעקב ללא תמונת מצב.", "tips": "עליך תחילה לסנן לפי אובייקטים במעקב שיש להם תמונת מצב.<br /><br />לא ניתן לשלוח ל-Frigate+ אובייקטים במעקב ללא תמונת מצב.",
@ -26,7 +26,7 @@
} }
}, },
"dates": { "dates": {
"selectPreset": "בחר פריסט…", "selectPreset": "בחר הגדרה…",
"all": { "all": {
"title": "כל התאריכים", "title": "כל התאריכים",
"short": "תאריכים" "short": "תאריכים"
@ -71,16 +71,16 @@
"title": "הגדרות", "title": "הגדרות",
"defaultView": { "defaultView": {
"summary": "סיכום", "summary": "סיכום",
"unfilteredGrid": "תצוגה מלאה", "unfilteredGrid": "טבלה לא מסוננת",
"title": "תצוגת ברירת מחדל", "title": "תצוגת ברירת מחדל",
"desc": "כאשר לא נבחרו מסננים, הצג סיכום של האובייקטים האחרונים שעברו מעקב לפי תווית, או הצג רשת לא מסוננת." "desc": "כאשר לא נבחרו מסננים, הצג סיכום של האובייקטים האחרונים שעברו מעקב לפי תווית, או הצג רשת לא מסוננת."
}, },
"gridColumns": { "gridColumns": {
"title": "עמודות גריד", "title": "עמודות טבלה",
"desc": "בחר את מספר העמודות בגריד." "desc": "בחר את מספר העמודות בטבלה."
}, },
"searchSource": { "searchSource": {
"label": "מקור חיפוש", "label": "חיפוש במקור",
"desc": "בחר אם לחפש בתמונות הממוזערות או בתיאורים של האובייקטים שבמעקב.", "desc": "בחר אם לחפש בתמונות הממוזערות או בתיאורים של האובייקטים שבמעקב.",
"options": { "options": {
"thumbnailImage": "תמונה ממוזערת", "thumbnailImage": "תמונה ממוזערת",
@ -100,7 +100,7 @@
"error": "מחיקת אובייקטים במעקב נכשלה: {{errorMessage}}" "error": "מחיקת אובייקטים במעקב נכשלה: {{errorMessage}}"
}, },
"title": "אישור מחיקה", "title": "אישור מחיקה",
"desc": "מחיקת אובייקטים אלה שעברו מעקב ({{objectLength}}) מסירה את לכידת התמונה, כל ההטמעות שנשמרו וכל ערכי שלבי האובייקט המשויכים. קטעי וידאו מוקלטים של אובייקטים אלה שעברו מעקב בתצוגת היסטוריה <em>לא</em> יימחקו.<br /><br />האם אתה בטוח שברצונך להמשיך?<br /><br />החזק את מקש <em>Shift</em> כדי לעקוף תיבת דו-שיח זו בעתיד." "desc": "מחיקת אובייקטים אלה ({{objectLength}}) שעברו מעקב מסירה את לכידת התמונה, כל ההטמעות שנשמרו וכל ערכי שלבי האובייקט המשויכים. קטעי וידאו מוקלטים של אובייקטים אלה שעברו מעקב בתצוגת היסטוריה <em>לא</em> יימחקו.<br /><br />האם אתה בטוח שברצונך להמשיך?<br /><br />החזק את מקש <em>Shift</em> כדי לעקוף תיבת דו-שיח זו בעתיד."
}, },
"zoneMask": { "zoneMask": {
"filterBy": "סינון לפי מיסוך אזור" "filterBy": "סינון לפי מיסוך אזור"
@ -111,16 +111,26 @@
"loading": "טוען לוחיות רישוי מזוהות…", "loading": "טוען לוחיות רישוי מזוהות…",
"placeholder": "הקלד כדי לחפש לוחיות רישוי…", "placeholder": "הקלד כדי לחפש לוחיות רישוי…",
"noLicensePlatesFound": "לא נמצאו לוחיות רישוי.", "noLicensePlatesFound": "לא נמצאו לוחיות רישוי.",
"selectPlatesFromList": "בחירת לוחית אחת או יותר מהרשימה." "selectPlatesFromList": "בחירת לוחית אחת או יותר מהרשימה.",
"selectAll": "בחר הכל",
"clearAll": "נקה הכל"
}, },
"logSettings": { "logSettings": {
"label": "סינון רמת לוג", "label": "סינון רמת לוג",
"filterBySeverity": "סנן לוגים לפי חומרה", "filterBySeverity": "סנן לוגים לפי חוּמרָה",
"loading": { "loading": {
"title": "טוען", "title": "טוען",
"desc": "כאשר חלונית הלוגים גוללת לתחתית, לוגים חדשים מוזרמים אוטומטית עם הוספתם." "desc": "כאשר חלונית הלוגים מגוללת לתחתית, לוגים חדשים מוזרמים אוטומטית עם הוספתם."
}, },
"disableLogStreaming": "השבתת זרימה של לוגים", "disableLogStreaming": "השבתת זרימה של לוגים",
"allLogs": "כל הלוגים" "allLogs": "כל הלוגים"
},
"classes": {
"label": "מחלקות",
"all": {
"title": "כל המחלקות"
},
"count_one": "{{count}} מחלקה",
"count_other": "{{count}} מחלקות"
} }
} }

View File

@ -1,5 +1,5 @@
{ {
"documentTitle": "עורך הגדרות - פריגטה", "documentTitle": "עורך הגדרות - Frigate",
"configEditor": "עורך תצורה", "configEditor": "עורך תצורה",
"copyConfig": "העתקת הגדרות", "copyConfig": "העתקת הגדרות",
"saveAndRestart": "שמירה והפעלה מחדש", "saveAndRestart": "שמירה והפעלה מחדש",
@ -12,5 +12,7 @@
"error": { "error": {
"savingError": "שגיאה בשמירת ההגדרות" "savingError": "שגיאה בשמירת ההגדרות"
} }
} },
"safeConfigEditor": "עורך תצורה (מצב בטוח)",
"safeModeDescription": "Frigate במצב בטוח עקב שגיאת אימות הגדרות."
} }

View File

@ -34,5 +34,16 @@
"selected_one": "נבחרו {{count}}", "selected_one": "נבחרו {{count}}",
"selected_other": "{{count}} נבחרו", "selected_other": "{{count}} נבחרו",
"camera": "מצלמה", "camera": "מצלמה",
"detected": "זוהה" "detected": "זוהה",
"detail": {
"noDataFound": "אין נתונים מפורטים לבדיקה",
"aria": "הפעלה/כיבוי תצוגת פרטים",
"trackedObject_one": "אובייקט במעקב",
"trackedObject_other": "אובייקטים במעקב",
"noObjectDetailData": "אין נתוני אובייקט זמינים."
},
"objectTrack": {
"trackedPoint": "נקודה במעקב",
"clickToSeek": "לחץ כדי לחפש את הזמן הזה"
}
} }

View File

@ -63,7 +63,15 @@
"label": "לחץ בתוך המסגרת כדי למרכז את המצלמה הממונעת" "label": "לחץ בתוך המסגרת כדי למרכז את המצלמה הממונעת"
} }
}, },
"presets": "מצלמה ממונעת - פריסטים" "presets": "מצלמה ממונעת - פריסטים",
"focus": {
"in": {
"label": "כניסת פוקוס מצלמת PTZ"
},
"out": {
"label": "יציאת פוקוס מצלמת PTZ"
}
}
}, },
"camera": { "camera": {
"enable": "אפשור מצלמה", "enable": "אפשור מצלמה",

View File

@ -1,5 +1,5 @@
{ {
"filter": "לסנן", "filter": "מסנן",
"export": "ייצוא", "export": "ייצוא",
"calendar": "לוח שנה", "calendar": "לוח שנה",
"filters": "מסננים", "filters": "מסננים",

View File

@ -268,7 +268,9 @@
"notifications": "הגדרת התראות - Frigate", "notifications": "הגדרת התראות - Frigate",
"authentication": "הגדרות אימות - Frigate", "authentication": "הגדרות אימות - Frigate",
"default": "הגדרות - Frigate", "default": "הגדרות - Frigate",
"general": "הגדרות כלליות - Frigate" "general": "הגדרות כלליות - Frigate",
"cameraManagement": "ניהול מצלמות - Frigate",
"cameraReview": "הגדרות סקירת מצלמה - Frigate"
}, },
"menu": { "menu": {
"ui": "UI - ממשק משתמש", "ui": "UI - ממשק משתמש",
@ -280,7 +282,10 @@
"notifications": "התראות", "notifications": "התראות",
"frigateplus": "+Frigate", "frigateplus": "+Frigate",
"enrichments": "תוספות", "enrichments": "תוספות",
"triggers": "הפעלות" "triggers": "הפעלות",
"cameraManagement": "ניהול",
"cameraReview": "סְקִירָה",
"roles": "תפקידים"
}, },
"dialog": { "dialog": {
"unsavedChanges": { "unsavedChanges": {

View File

@ -52,7 +52,8 @@
"inferenceSpeed": "מהירות זיהוי", "inferenceSpeed": "מהירות זיהוי",
"temperature": "טמפרטורת הגלאי", "temperature": "טמפרטורת הגלאי",
"cpuUsage": "ניצול מעבד על ידי הגלאי", "cpuUsage": "ניצול מעבד על ידי הגלאי",
"memoryUsage": "שימוש בזיכרון על ידי הגלאי" "memoryUsage": "שימוש בזיכרון על ידי הגלאי",
"cpuUsageInformation": "המעבד המשמש להכנת נתוני קלט ופלט אל/ממודלי זיהוי. ערך זה אינו מודד את השימוש בהסקה, גם אם נעשה שימוש במעבד גרפי או מאיץ."
}, },
"hardwareInfo": { "hardwareInfo": {
"gpuMemory": "זיכרון GPU", "gpuMemory": "זיכרון GPU",

View File

@ -176,7 +176,7 @@
}, },
"role": { "role": {
"viewer": "Néző", "viewer": "Néző",
"title": "Szerep", "title": "Szerepkör",
"admin": "Adminisztrátor", "admin": "Adminisztrátor",
"desc": "Az adminisztrátoroknak teljes hozzáférése van az összes feature-höz. A nézők csak a kamerákat láthatják, áttekinthetik az elemeket és az előzményeket a UI-on." "desc": "Az adminisztrátoroknak teljes hozzáférése van az összes feature-höz. A nézők csak a kamerákat láthatják, áttekinthetik az elemeket és az előzményeket a UI-on."
}, },
@ -221,6 +221,14 @@
"length": { "length": {
"feet": "láb", "feet": "láb",
"meters": "méter" "meters": "méter"
},
"data": {
"kbps": "kB/s",
"mbps": "MB/s",
"gbps": "GB/s",
"kbph": "kB/óra",
"mbph": "MB/óra",
"gbph": "GB/óra"
} }
}, },
"button": { "button": {
@ -263,5 +271,8 @@
"label": { "label": {
"back": "Vissza" "back": "Vissza"
}, },
"readTheDocumentation": "Olvassa el a dokumentációt" "readTheDocumentation": "Olvassa el a dokumentációt",
"information": {
"pixels": "{{area}}px"
}
} }

View File

@ -4,7 +4,7 @@
"button": "Újraindítás", "button": "Újraindítás",
"restarting": { "restarting": {
"title": "A Frigate újraindul", "title": "A Frigate újraindul",
"content": "Az oldal újrtölt {{countdown}} másodperc múlva.", "content": "Az oldal újratölt {{countdown}} másodperc múlva.",
"button": "Erőltetett újraindítás azonnal" "button": "Erőltetett újraindítás azonnal"
} }
}, },
@ -107,7 +107,8 @@
"button": { "button": {
"markAsReviewed": "Megjelölés áttekintettként", "markAsReviewed": "Megjelölés áttekintettként",
"deleteNow": "Törlés Most", "deleteNow": "Törlés Most",
"export": "Exportálás" "export": "Exportálás",
"markAsUnreviewed": "Megjelölés nem ellenőrzöttként"
} }
}, },
"imagePicker": { "imagePicker": {

View File

@ -134,6 +134,9 @@
"playInBackground": { "playInBackground": {
"label": "Lejátszás a háttérben", "label": "Lejátszás a háttérben",
"tips": "Engedélyezze ezt az opciót a folyamatos közvetítéshez akkor is, ha a lejátszó rejtve van." "tips": "Engedélyezze ezt az opciót a folyamatos közvetítéshez akkor is, ha a lejátszó rejtve van."
},
"debug": {
"picker": "A stream kiválasztása nem érhető el hibakeresési módban. A hibakeresési nézet mindig az észlelési szerepkörhöz rendelt streamet használja."
} }
}, },
"cameraSettings": { "cameraSettings": {
@ -167,5 +170,16 @@
"transcription": { "transcription": {
"enable": "Élő Audio Feliratozás Engedélyezése", "enable": "Élő Audio Feliratozás Engedélyezése",
"disable": "Élő Audio Feliratozás Kikapcsolása" "disable": "Élő Audio Feliratozás Kikapcsolása"
},
"noCameras": {
"title": "Nincsenek kamerák beállítva",
"description": "Kezdje egy kamera csatlakoztatásával.",
"buttonText": "Kamera hozzáadása"
},
"snapshot": {
"takeSnapshot": "Azonnali pillanatkép letöltése",
"noVideoSource": "Ehhez a pillanatképhez videó forrás nem elérhető.",
"captureFailed": "Pillanatkép készítése sikertelen.",
"downloadStarted": "Pillanatkép letöltése elindítva."
} }
} }

View File

@ -10,7 +10,9 @@
"frigatePlus": "Frigate+ beállítások - Frigate", "frigatePlus": "Frigate+ beállítások - Frigate",
"notifications": "Értesítések beállítása - Frigate", "notifications": "Értesítések beállítása - Frigate",
"motionTuner": "Mozgás Hangoló - Frigate", "motionTuner": "Mozgás Hangoló - Frigate",
"enrichments": "Kiegészítés Beállítások - Frigate" "enrichments": "Kiegészítés Beállítások - Frigate",
"cameraManagement": "Kamerák kezelése - Frigate",
"cameraReview": "Kamera beállítások áttekintése Frigate"
}, },
"menu": { "menu": {
"ui": "UI", "ui": "UI",
@ -23,7 +25,10 @@
"notifications": "Értesítések", "notifications": "Értesítések",
"frigateplus": "Frigate+", "frigateplus": "Frigate+",
"enrichments": "Extra funkciók", "enrichments": "Extra funkciók",
"triggers": "Triggerek" "triggers": "Triggerek",
"roles": "Szerepkörök",
"cameraManagement": "Menedzsment",
"cameraReview": "Vizsgálat"
}, },
"dialog": { "dialog": {
"unsavedChanges": { "unsavedChanges": {
@ -254,7 +259,8 @@
"admin": "Adminisztrátor", "admin": "Adminisztrátor",
"intro": "Válassza ki a megfelelő szerepkört ehhez a felhasználóhoz:", "intro": "Válassza ki a megfelelő szerepkört ehhez a felhasználóhoz:",
"adminDesc": "Teljes hozzáférés az összes funkcióhoz.", "adminDesc": "Teljes hozzáférés az összes funkcióhoz.",
"viewerDesc": "Csak az Élő irányítópultokhoz, Ellenőrzéshez, Felfedezéshez és Exportokhoz korlátozva." "viewerDesc": "Csak az Élő irányítópultokhoz, Ellenőrzéshez, Felfedezéshez és Exportokhoz korlátozva.",
"customDesc": "Egyéni szerepkör meghatározott kamerahozzáféréssel."
}, },
"title": "Felhasználói szerepkör módosítása", "title": "Felhasználói szerepkör módosítása",
"select": "Válasszon szerepkört", "select": "Válasszon szerepkört",
@ -317,7 +323,7 @@
"username": "Felhasználói név", "username": "Felhasználói név",
"password": "Jelszó", "password": "Jelszó",
"deleteUser": "Felhasználó törlése", "deleteUser": "Felhasználó törlése",
"actions": "Műveletek", "actions": "Akciók",
"role": "Szerepkör", "role": "Szerepkör",
"changeRole": "felhasználói szerepkör módosítása" "changeRole": "felhasználói szerepkör módosítása"
}, },
@ -749,6 +755,11 @@
"error": { "error": {
"min": "Legalább egy műveletet ki kell választani." "min": "Legalább egy műveletet ki kell választani."
} }
},
"friendly_name": {
"title": "Barátságos név",
"placeholder": "Nevezd meg vagy írd le ezt a triggert",
"description": "Egy opcionális felhasználóbarát név vagy leíró szöveg ehhez az eseményindítóhoz."
} }
} }
}, },
@ -763,6 +774,79 @@
"updateTriggerFailed": "A trigger módosítása sikertelen: {{errorMessage}}", "updateTriggerFailed": "A trigger módosítása sikertelen: {{errorMessage}}",
"deleteTriggerFailed": "A trigger törlése sikertelen: {{errorMessage}}" "deleteTriggerFailed": "A trigger törlése sikertelen: {{errorMessage}}"
} }
},
"semanticSearch": {
"title": "Szemantikus keresés le van tiltva",
"desc": "A Triggerek használatához engedélyezni kell a szemantikus keresést."
}
},
"roles": {
"management": {
"title": "Megtekintői szerepkör-kezelés",
"desc": "Kezelje az egyéni nézői szerepköröket és a kamera-hozzáférési engedélyeiket ehhez a Frigate-példányhoz."
},
"addRole": "Szerepkör hozzáadása",
"table": {
"role": "Szerepkör",
"cameras": "Kamerák",
"actions": "Akciók",
"noRoles": "Nem találhatók egyéni szerepkörök.",
"editCameras": "Kamerák módosítása",
"deleteRole": "Szerepkör törlése"
},
"toast": {
"success": {
"createRole": "Szerepkör létrehozva: {{role}}",
"updateCameras": "Kamerák frissítve a szerepkörhöz: {{role}}",
"deleteRole": "Szerepkör sikeresen törölve: {{role}}",
"userRolesUpdated": "{{count}} felhasználó, akit ehhez a szerepkörhöz rendeltünk, frissült „néző”-re, amely hozzáféréssel rendelkezik az összes kamerához."
},
"error": {
"createRoleFailed": "Nem sikerült létrehozni a szerepkört: {{errorMessage}}",
"updateCamerasFailed": "Nem sikerült frissíteni a kamerákat: {{errorMessage}}",
"deleteRoleFailed": "Nem sikerült törölni a szerepkört: {{errorMessage}}",
"userUpdateFailed": "Nem sikerült frissíteni a felhasználói szerepköröket: {{errorMessage}}"
}
},
"dialog": {
"createRole": {
"title": "Új szerepkör létrehozása",
"desc": "Adjon hozzá egy új szerepkört, és adja meg a kamera hozzáférési engedélyeit."
},
"editCameras": {
"title": "Szerepkör kamerák szerkesztése",
"desc": "Frissítse a kamerahozzáférést a(z) <strong>{{role}}</strong> szerepkörhöz."
},
"deleteRole": {
"title": "Szerepkör törlése",
"desc": "Ez a művelet nem vonható vissza. Ez véglegesen törli a szerepkört, és az ezzel a szerepkörrel rendelkező összes felhasználót a „megtekintő” szerepkörhöz rendeli, amivel a megtekintő hozzáférhet az összes kamerához.",
"warn": "Biztosan törölni szeretnéd a(z) <strong>{{role}}</strong> szerepkört?",
"deleting": "Törlés..."
},
"form": {
"role": {
"title": "Szerepkör neve",
"placeholder": "Adja meg a szerepkör nevét",
"desc": "Csak betűk, számok, pontok és aláhúzásjelek engedélyezettek.",
"roleIsRequired": "A szerepkör nevének megadása kötelező",
"roleOnlyInclude": "A szerepkör neve csak betűket, számokat , . vagy _ karaktereket tartalmazhat",
"roleExists": "Már létezik egy ilyen nevű szerepkör."
},
"cameras": {
"title": "Kamerák",
"desc": "Válassza ki azokat a kamerákat, amelyekhez ennek a szerepkörnek hozzáférése van. Legalább egy kamera megadása szükséges.",
"required": "Legalább egy kamerát ki kell választani."
}
}
}
},
"cameraWizard": {
"title": "Kamera hozzáadása",
"description": "Kövesse az alábbi lépéseket, hogy új kamerát adjon hozzá a Frigate telepítéséhez.",
"steps": {
"nameAndConnection": "Név & adatkapcsolat",
"streamConfiguration": "Stream beállítások",
"validationAndTesting": "Validálás és tesztelés"
} }
} }
} }

View File

@ -81,5 +81,8 @@
"electric_guitar": "Gitar Elektrik", "electric_guitar": "Gitar Elektrik",
"acoustic_guitar": "Gitar Akustik", "acoustic_guitar": "Gitar Akustik",
"strum": "Genjreng", "strum": "Genjreng",
"banjo": "Banjo" "banjo": "Banjo",
"snoring": "Ngorok",
"cough": "Batuk",
"clapping": "Tepukan"
} }

View File

@ -8,6 +8,11 @@
"motionTuner": "Penyetel Gerakan - Frigate", "motionTuner": "Penyetel Gerakan - Frigate",
"general": "Frigate - Pengaturan Umum", "general": "Frigate - Pengaturan Umum",
"object": "Debug - Frigate", "object": "Debug - Frigate",
"enrichments": "Frigate - Pengaturan Pengayaan" "enrichments": "Frigate - Pengaturan Pengayaan",
"cameraManagement": "Pengaturan Kamera - Frigate"
},
"menu": {
"cameraManagement": "Pengaturan",
"notifications": "Notifikasi"
} }
} }

View File

@ -425,5 +425,13 @@
"white_noise": "Rumore bianco", "white_noise": "Rumore bianco",
"pink_noise": "Rumore rosa", "pink_noise": "Rumore rosa",
"field_recording": "Registrazione sul campo", "field_recording": "Registrazione sul campo",
"scream": "Grido" "scream": "Grido",
"vibration": "Vibrazione",
"sodeling": "Zollatura",
"chird": "Accordo",
"change_ringing": "Cambia suoneria",
"shofar": "Shofar",
"liquid": "Liquido",
"splash": "Schizzo",
"slosh": "Sciabordio"
} }

View File

@ -134,6 +134,14 @@
"length": { "length": {
"feet": "piedi", "feet": "piedi",
"meters": "metri" "meters": "metri"
},
"data": {
"kbps": "kB/s",
"mbps": "MB/s",
"gbps": "GB/s",
"kbph": "kB/ora",
"mbph": "MB/ora",
"gbph": "GB/ora"
} }
}, },
"label": { "label": {
@ -280,5 +288,8 @@
} }
}, },
"selectItem": "Seleziona {{item}}", "selectItem": "Seleziona {{item}}",
"readTheDocumentation": "Leggi la documentazione" "readTheDocumentation": "Leggi la documentazione",
"information": {
"pixels": "{{area}}px"
}
} }

View File

@ -110,7 +110,8 @@
"button": { "button": {
"export": "Esporta", "export": "Esporta",
"markAsReviewed": "Segna come visto", "markAsReviewed": "Segna come visto",
"deleteNow": "Elimina ora" "deleteNow": "Elimina ora",
"markAsUnreviewed": "Segna come non visto"
}, },
"confirmDelete": { "confirmDelete": {
"desc": { "desc": {

View File

@ -37,5 +37,16 @@
"selected_other": "{{count}} selezionati", "selected_other": "{{count}} selezionati",
"detected": "rilevato", "detected": "rilevato",
"suspiciousActivity": "Attività sospetta", "suspiciousActivity": "Attività sospetta",
"threateningActivity": "Attività minacciosa" "threateningActivity": "Attività minacciosa",
"detail": {
"noDataFound": "Nessun dato dettagliato da rivedere",
"aria": "Attiva/disattiva la visualizzazione dettagliata",
"trackedObject_one": "oggetto tracciato",
"trackedObject_other": "oggetti tracciati",
"noObjectDetailData": "Non sono disponibili dati dettagliati sull'oggetto."
},
"objectTrack": {
"trackedPoint": "Punto tracciato",
"clickToSeek": "Premi per cercare in questo momento"
}
} }

View File

@ -55,7 +55,7 @@
}, },
"imageEntry": { "imageEntry": {
"dropActive": "Rilascia l'immagine qui…", "dropActive": "Rilascia l'immagine qui…",
"dropInstructions": "Trascina e rilascia un'immagine qui oppure fai clic per selezionarla", "dropInstructions": "Trascina e rilascia o incolla un'immagine qui oppure fai clic per selezionarla",
"maxSize": "Dimensione massima: {{size}} MB", "maxSize": "Dimensione massima: {{size}} MB",
"validation": { "validation": {
"selectImage": "Seleziona un file immagine." "selectImage": "Seleziona un file immagine."

View File

@ -12,8 +12,8 @@
}, },
"manualRecording": { "manualRecording": {
"recordDisabledTips": "Poiché la registrazione è disabilitata o limitata nella configurazione di questa telecamera, verrà salvata solo un'istantanea.", "recordDisabledTips": "Poiché la registrazione è disabilitata o limitata nella configurazione di questa telecamera, verrà salvata solo un'istantanea.",
"title": "Registrazione su richiesta", "title": "Su richiesta",
"tips": "Avvia un evento manuale in base alle impostazioni di conservazione della registrazione di questa telecamera.", "tips": "Scarica un'istantanea attuale o avvia un evento manuale in base alle impostazioni di conservazione della registrazione di questa telecamera.",
"playInBackground": { "playInBackground": {
"label": "Riproduci in sottofondo", "label": "Riproduci in sottofondo",
"desc": "Abilita questa opzione per continuare la trasmissione quando il lettore è nascosto." "desc": "Abilita questa opzione per continuare la trasmissione quando il lettore è nascosto."
@ -147,6 +147,9 @@
"lowBandwidth": { "lowBandwidth": {
"tips": "La visualizzazione dal vivo è in modalità a bassa larghezza di banda a causa di errori di caricamento o di trasmissione.", "tips": "La visualizzazione dal vivo è in modalità a bassa larghezza di banda a causa di errori di caricamento o di trasmissione.",
"resetStream": "Reimposta flusso" "resetStream": "Reimposta flusso"
},
"debug": {
"picker": "Selezione del flusso non disponibile in modalità correzioni. La visualizzazione correzioni utilizza sempre il flusso a cui è assegnato il ruolo di rilevamento."
} }
}, },
"effectiveRetainMode": { "effectiveRetainMode": {
@ -167,5 +170,16 @@
"transcription": { "transcription": {
"enable": "Abilita la trascrizione audio in tempo reale", "enable": "Abilita la trascrizione audio in tempo reale",
"disable": "Disabilita la trascrizione audio in tempo reale" "disable": "Disabilita la trascrizione audio in tempo reale"
},
"noCameras": {
"buttonText": "Aggiungi telecamera",
"title": "Nessuna telecamera configurata",
"description": "Per iniziare, collega una telecamera."
},
"snapshot": {
"takeSnapshot": "Scarica l'istantanea attuale",
"noVideoSource": "Nessuna sorgente video disponibile per l'istantanea.",
"captureFailed": "Impossibile catturare l'istantanea.",
"downloadStarted": "Scaricamento istantanea avviato."
} }
} }

View File

@ -10,7 +10,9 @@
"general": "Impostazioni generali - Frigate", "general": "Impostazioni generali - Frigate",
"frigatePlus": "Impostazioni Frigate+ - Frigate", "frigatePlus": "Impostazioni Frigate+ - Frigate",
"notifications": "Impostazioni di notifiche - Frigate", "notifications": "Impostazioni di notifiche - Frigate",
"enrichments": "Impostazioni di miglioramento - Frigate" "enrichments": "Impostazioni di miglioramento - Frigate",
"cameraManagement": "Gestisci telecamere - Frigate",
"cameraReview": "Impostazioni revisione telecamera - Frigate"
}, },
"frigatePlus": { "frigatePlus": {
"snapshotConfig": { "snapshotConfig": {
@ -378,7 +380,10 @@
"users": "Utenti", "users": "Utenti",
"frigateplus": "Frigate+", "frigateplus": "Frigate+",
"enrichments": "Miglioramenti", "enrichments": "Miglioramenti",
"triggers": "Inneschi" "triggers": "Inneschi",
"roles": "Ruoli",
"cameraManagement": "Gestione",
"cameraReview": "Rivedi"
}, },
"users": { "users": {
"dialog": { "dialog": {
@ -815,6 +820,11 @@
"error": { "error": {
"min": "È necessario selezionare almeno un'azione." "min": "È necessario selezionare almeno un'azione."
} }
},
"friendly_name": {
"title": "Nome semplice",
"placeholder": "Assegna un nome o descrivi questo innesco",
"description": "Un nome semplice o un testo descrittivo facoltativo per questo innesco."
} }
} }
}, },
@ -829,6 +839,10 @@
"updateTriggerFailed": "Impossibile aggiornare l'innesco: {{errorMessage}}", "updateTriggerFailed": "Impossibile aggiornare l'innesco: {{errorMessage}}",
"deleteTriggerFailed": "Impossibile eliminare l'innesco: {{errorMessage}}" "deleteTriggerFailed": "Impossibile eliminare l'innesco: {{errorMessage}}"
} }
},
"semanticSearch": {
"title": "La ricerca semantica è disabilitata",
"desc": "Per utilizzare gli inneschi, è necessario abilitare la ricerca semantica."
} }
}, },
"roles": { "roles": {
@ -890,5 +904,222 @@
} }
} }
} }
},
"cameraReview": {
"title": "Impostazioni revisione telecamera",
"object_descriptions": {
"title": "Descrizioni oggetti IA generativa",
"desc": "Abilita/disabilita temporaneamente le descrizioni degli oggetti generate dall'IA per questa telecamera. Se disabilitate, le descrizioni generate dall'IA non verranno richieste per gli oggetti tracciati su questa telecamera."
},
"review_descriptions": {
"title": "Descrizioni revisioni IA generativa",
"desc": "Abilita/disabilita temporaneamente le descrizioni delle revisioni generate dall'IA per questa telecamera. Se disabilitate, le descrizioni generate dall'IA non verranno richieste per gli elementi da rivedere su questa telecamera."
},
"review": {
"title": "Rivedi",
"desc": "Abilita/disabilita temporaneamente avvisi e rilevamenti per questa telecamera fino al riavvio di Frigate. Se disabilitato, non verranno generati nuovi elementi di revisione. ",
"alerts": "Avvisi ",
"detections": "Rilevamenti "
},
"reviewClassification": {
"title": "Classificazione revisione",
"desc": "Frigate categorizza gli elementi di revisione come Avvisi e Rilevamenti. Per impostazione predefinita, tutti gli oggetti <em>persona</em> e <em>auto</em> sono considerati Avvisi. È possibile perfezionare la categorizzazione degli elementi di revisione configurando le zone richieste per ciascuno di essi.",
"noDefinedZones": "Per questa telecamera non sono definite zone.",
"objectAlertsTips": "Tutti gli oggetti {{alertsLabels}} su {{cameraName}} verranno mostrati come Avvisi.",
"zoneObjectAlertsTips": "Tutti gli oggetti {{alertsLabels}} rilevati in {{zone}} su {{cameraName}} verranno mostrati come Avvisi.",
"objectDetectionsTips": "Tutti gli oggetti {{detectionsLabels}} non categorizzati su {{cameraName}} verranno mostrati come Rilevamenti, indipendentemente dalla zona in cui si trovano.",
"zoneObjectDetectionsTips": {
"text": "Tutti gli oggetti {{detectionsLabels}} non categorizzati in {{zone}} su {{cameraName}} verranno mostrati come Rilevamenti.",
"notSelectDetections": "Tutti gli oggetti {{detectionsLabels}} rilevati in {{zone}} su {{cameraName}} non classificati come Avvisi verranno mostrati come Rilevamenti, indipendentemente dalla zona in cui si trovano.",
"regardlessOfZoneObjectDetectionsTips": "Tutti gli oggetti {{detectionsLabels}} non categorizzati su {{cameraName}} verranno mostrati come Rilevamenti, indipendentemente dalla zona in cui si trovano."
},
"unsavedChanges": "Impostazioni di classificazione delle revisioni non salvate per {{camera}}",
"selectAlertsZones": "Seleziona le zone per gli Avvisi",
"selectDetectionsZones": "Seleziona le zone per i Rilevamenti",
"limitDetections": "Limita i rilevamenti a zone specifiche",
"toast": {
"success": "La configurazione della classificazione di revisione è stata salvata. Riavvia Frigate per applicare le modifiche."
}
}
},
"cameraWizard": {
"step3": {
"streamUnavailable": "Anteprima trasmissione non disponibile",
"description": "Convalida e analisi finale prima di salvare la nuova telecamera. Connetti ogni flusso prima di salvare.",
"validationTitle": "Convalida del flusso",
"connectAllStreams": "Connetti tutti i flussi",
"reconnectionSuccess": "Riconnessione riuscita.",
"reconnectionPartial": "Alcuni flussi non sono riusciti a riconnettersi.",
"reload": "Ricarica",
"connecting": "Connessione...",
"streamTitle": "Flusso {{number}}",
"valid": "Convalida",
"failed": "Fallito",
"notTested": "Non verificata",
"connectStream": "Connetti",
"connectingStream": "Connessione",
"disconnectStream": "Disconnetti",
"estimatedBandwidth": "Larghezza di banda stimata",
"roles": "Ruoli",
"none": "Nessuno",
"error": "Errore",
"streamValidated": "Flusso {{number}} convalidato con successo",
"streamValidationFailed": "Convalida del flusso {{number}} non riuscita",
"saveAndApply": "Salva nuova telecamera",
"saveError": "Configurazione non valida. Controlla le impostazioni.",
"issues": {
"title": "Convalida del flusso",
"videoCodecGood": "Il codec video è {{codec}}.",
"audioCodecGood": "Il codec audio è {{codec}}.",
"noAudioWarning": "Nessun audio rilevato per questo flusso, le registrazioni non avranno audio.",
"audioCodecRecordError": "Per supportare l'audio nelle registrazioni è necessario il codec audio AAC.",
"audioCodecRequired": "Per supportare il rilevamento audio è necessario un flusso audio.",
"restreamingWarning": "Riducendo le connessioni alla telecamera per il flusso di registrazione l'utilizzo della CPU potrebbe aumentare leggermente.",
"dahua": {
"substreamWarning": "Il flusso 1 è bloccato a bassa risoluzione. Molte telecamere Dahua/Amcrest/EmpireTech supportano flussi aggiuntivi che devono essere abilitati nelle impostazioni della telecamera. Si consiglia di controllare e utilizzare tali flussi, se disponibili."
},
"hikvision": {
"substreamWarning": "Il flusso 1 è bloccato a bassa risoluzione. Molte telecamere Hikvision supportano flussi aggiuntivi che devono essere abilitati nelle impostazioni della telecamera. Si consiglia di controllare e utilizzare tali flussi, se disponibili."
}
}
},
"title": "Aggiungi telecamera",
"description": "Per aggiungere una nuova telecamera alla tua installazione Frigate, segui i passaggi indicati di seguito.",
"steps": {
"nameAndConnection": "Nome e connessione",
"streamConfiguration": "Configurazione flusso",
"validationAndTesting": "Validazione e prova"
},
"save": {
"success": "Nuova telecamera {{cameraName}} salvata correttamente.",
"failure": "Errore durante il salvataggio di {{cameraName}}."
},
"testResultLabels": {
"resolution": "Risoluzione",
"video": "Video",
"audio": "Audio",
"fps": "FPS"
},
"commonErrors": {
"noUrl": "Si prega di fornire un URL di flusso valido",
"testFailed": "Prova del flusso fallita: {{error}}"
},
"step1": {
"description": "Inserisci i dettagli della tua telecamera e verifica la connessione.",
"cameraName": "Nome telecamera",
"cameraNamePlaceholder": "ad esempio, porta_anteriore o Panoramica cortile",
"host": "Indirizzo sistema/IP",
"port": "Porta",
"username": "Nome utente",
"usernamePlaceholder": "Opzionale",
"password": "Password",
"passwordPlaceholder": "Opzionale",
"selectTransport": "Seleziona il protocollo di trasmissione",
"cameraBrand": "Marca telecamera",
"selectBrand": "Seleziona la marca della telecamera per il modello URL",
"customUrl": "URL del flusso personalizzato",
"brandInformation": "Informazioni sul marchio",
"brandUrlFormat": "Per le telecamere con formato URL RTSP come: {{exampleUrl}}",
"customUrlPlaceholder": "rtsp://nomeutente:password@sistema:porta/percorso",
"testConnection": "Prova connessione",
"testSuccess": "Prova di connessione riuscita!",
"testFailed": "Prova di connessione fallita. Controlla i dati immessi e riprova.",
"streamDetails": "Dettagli del flusso",
"warnings": {
"noSnapshot": "Impossibile recuperare un'immagine dal flusso configurato."
},
"errors": {
"brandOrCustomUrlRequired": "Seleziona una marca di telecamera con sistema/IP oppure scegli \"Altro\" con un URL personalizzato",
"nameRequired": "Il nome della telecamera è obbligatorio",
"nameLength": "Il nome della telecamera deve contenere al massimo 64 caratteri",
"invalidCharacters": "Il nome della telecamera contiene caratteri non validi",
"nameExists": "Il nome della telecamera esiste già",
"brands": {
"reolink-rtsp": "Reolink RTSP non è consigliato. Si consiglia di abilitare http nelle impostazioni della telecamera e riavviare la procedura guidata."
}
},
"docs": {
"reolink": "https://docs.frigate.video/configuration/camera_specific.html#reolink-cameras"
}
},
"step2": {
"description": "Configura i ruoli del flusso e aggiungi altri flussi per la tua telecamera.",
"streamsTitle": "Flussi della telecamera",
"addStream": "Aggiungi flusso",
"addAnotherStream": "Aggiungi un altro flusso",
"streamTitle": "Flusso {{number}}",
"streamUrl": "URL del flusso",
"streamUrlPlaceholder": "rtsp://nomeutente:password@sistema:porta/percorso",
"url": "URL",
"resolution": "Risoluzione",
"selectResolution": "Seleziona la risoluzione",
"quality": "Qualità",
"selectQuality": "Seleziona la qualità",
"roles": "Ruoli",
"roleLabels": {
"detect": "Rilevamento oggetti",
"record": "Registrazione",
"audio": "Audio"
},
"testStream": "Prova connessione",
"testSuccess": "Prova del flusso riuscita!",
"testFailed": "Prova del flusso fallita",
"testFailedTitle": "Prova fallita",
"connected": "Connessa",
"notConnected": "Non connessa",
"featuresTitle": "Caratteristiche",
"go2rtc": "Riduci le connessioni alla telecamera",
"detectRoleWarning": "Per procedere, almeno un flusso deve avere il ruolo \"rileva\".",
"rolesPopover": {
"title": "Ruoli del flusso",
"detect": "Flusso principale per il rilevamento degli oggetti.",
"record": "Salva segmenti del flusso video in base alle impostazioni di configurazione.",
"audio": "Flusso per il rilevamento basato sull'audio."
},
"featuresPopover": {
"title": "Caratteristiche del flusso",
"description": "Utilizza la ritrasmissione go2rtc per ridurre le connessioni alla tua telecamera."
}
}
},
"cameraManagement": {
"title": "Gestisci telecamere",
"addCamera": "Aggiungi nuova telecamera",
"editCamera": "Modifica telecamera:",
"selectCamera": "Seleziona una telecamera",
"backToSettings": "Torna alle impostazioni della telecamera",
"streams": {
"title": "Abilita/Disabilita telecamere",
"desc": "Disattiva temporaneamente una telecamera fino al riavvio di Frigate. La disattivazione completa di una telecamera interrompe l'elaborazione dei flussi di questa telecamera da parte di Frigate. Rilevamento, registrazione e correzioni non saranno disponibili.<br /> <em>Nota: questa operazione non disattiva le ritrasmissioni di go2rtc.</em>"
},
"cameraConfig": {
"add": "Aggiungi telecamera",
"edit": "Modifica telecamera",
"description": "Configura le impostazioni della telecamera, inclusi gli ingressi ed i ruoli dei flussi.",
"name": "Nome telecamera",
"nameRequired": "Il nome della telecamera è obbligatorio",
"nameLength": "Il nome della telecamera deve contenere al massimo 64 caratteri.",
"namePlaceholder": "ad esempio, porta_anteriore o Panoramica cortile",
"toast": {
"success": "La telecamera {{cameraName}} è stata salvata correttamente"
},
"enabled": "Abilitata",
"ffmpeg": {
"inputs": "Flussi di ingresso",
"path": "Percorso del flusso",
"pathRequired": "Il percorso del flusso è obbligatorio",
"pathPlaceholder": "rtsp://...",
"roles": "Ruoli",
"rolesRequired": "È richiesto almeno un ruolo",
"rolesUnique": "Ogni ruolo (audio, rilevamento, registrazione) può essere assegnato solo ad un flusso",
"addInput": "Aggiungi flusso di ingresso",
"removeInput": "Rimuovi flusso di ingresso",
"inputsRequired": "È richiesto almeno un flusso di ingresso"
},
"go2rtcStreams": "Flussi go2rtc",
"streamUrls": "URL dei flussi",
"addUrl": "Aggiungi URL",
"addGo2rtcStream": "Aggiungi flusso go2rtc"
}
} }
} }

View File

@ -77,6 +77,14 @@
"length": { "length": {
"feet": "フィート", "feet": "フィート",
"meters": "メートル" "meters": "メートル"
},
"data": {
"gbph": "GB/hour",
"gbps": "GB/s",
"kbph": "kB/hour",
"kbps": "kB/s",
"mbph": "MB/hour",
"mbps": "MB/s"
} }
}, },
"label": { "label": {
@ -256,5 +264,8 @@
"title": "404", "title": "404",
"desc": "ページが見つかりません" "desc": "ページが見つかりません"
}, },
"selectItem": "{{item}} を選択" "selectItem": "{{item}} を選択",
"information": {
"pixels": "{{area}}ピクセル"
}
} }

View File

@ -105,7 +105,8 @@
"button": { "button": {
"export": "書き出し", "export": "書き出し",
"markAsReviewed": "レビュー済みにする", "markAsReviewed": "レビュー済みにする",
"deleteNow": "今すぐ削除" "deleteNow": "今すぐ削除",
"markAsUnreviewed": "未レビューに戻す"
} }
}, },
"imagePicker": { "imagePicker": {

View File

@ -90,7 +90,7 @@
} }
}, },
"downloadingModels": { "downloadingModels": {
"context": "Frigate はセマンティック検索をサポートするために必要な埋め込みモデルをダウンロードしています。ネットワーク速度により数分かかる場合があります。", "context": "Frigate はセマンティック検索(意味理解型画像検索)をサポートするために必要な埋め込みモデルをダウンロードしています。ネットワーク速度により数分かかる場合があります。",
"setup": { "setup": {
"visionModel": "ビジョンモデル", "visionModel": "ビジョンモデル",
"visionModelFeatureExtractor": "ビジョンモデル特徴抽出器", "visionModelFeatureExtractor": "ビジョンモデル特徴抽出器",

View File

@ -65,7 +65,7 @@
"selectImage": "画像ファイルを選択してください。" "selectImage": "画像ファイルを選択してください。"
}, },
"dropActive": "ここに画像をドロップ…", "dropActive": "ここに画像をドロップ…",
"dropInstructions": "画像をここにドラッグ&ドロップ、またはクリックして選択", "dropInstructions": "画像をここにドラッグ&ドロップ、ペースト、またはクリックして選択",
"maxSize": "最大サイズ: {{size}}MB" "maxSize": "最大サイズ: {{size}}MB"
}, },
"nofaces": "顔はありません", "nofaces": "顔はありません",

View File

@ -91,7 +91,7 @@
}, },
"manualRecording": { "manualRecording": {
"title": "オンデマンド録画", "title": "オンデマンド録画",
"tips": "このカメラの録画保持設定に基づく手動イベントを開始します。", "tips": "このカメラの録画保持設定に基づいて、即時スナップショットをダウンロードするか、手動イベントを開始してください。",
"playInBackground": { "playInBackground": {
"label": "バックグラウンドで再生", "label": "バックグラウンドで再生",
"desc": "プレーヤーが非表示の場合でもストリーミングを継続するにはこのオプションを有効にします。" "desc": "プレーヤーが非表示の場合でもストリーミングを継続するにはこのオプションを有効にします。"
@ -136,6 +136,9 @@
"playInBackground": { "playInBackground": {
"label": "バックグラウンドで再生", "label": "バックグラウンドで再生",
"tips": "プレーヤーが非表示でもストリーミングを継続するにはこのオプションを有効にします。" "tips": "プレーヤーが非表示でもストリーミングを継続するにはこのオプションを有効にします。"
},
"debug": {
"picker": "デバッグモードではストリームの選択はできません。デバッグビューは常に 検出ロールに割り当てられたストリームを使用します。"
} }
}, },
"cameraSettings": { "cameraSettings": {
@ -165,5 +168,16 @@
"label": "カメラグループを編集" "label": "カメラグループを編集"
}, },
"exitEdit": "編集を終了" "exitEdit": "編集を終了"
},
"noCameras": {
"title": "カメラが設定されていません",
"buttonText": "カメラを追加",
"description": "開始するには、カメラを接続してください。"
},
"snapshot": {
"takeSnapshot": "即時スナップショットをダウンロード",
"noVideoSource": "スナップショットに使用できる映像ソースがありません。",
"captureFailed": "スナップショットの取得に失敗しました。",
"downloadStarted": "スナップショットのダウンロードを開始しました。"
} }
} }

View File

@ -3,17 +3,19 @@
"authentication": "認証設定 - Frigate", "authentication": "認証設定 - Frigate",
"camera": "カメラ設定 - Frigate", "camera": "カメラ設定 - Frigate",
"default": "設定 - Frigate", "default": "設定 - Frigate",
"enrichments": "エンリッチメント設定 - Frigate", "enrichments": "高度解析設定 - Frigate",
"masksAndZones": "マスク/ゾーンエディタ - Frigate", "masksAndZones": "マスク/ゾーンエディタ - Frigate",
"motionTuner": "モーションチューナー - Frigate", "motionTuner": "モーションチューナー - Frigate",
"object": "デバッグ - Frigate", "object": "デバッグ - Frigate",
"general": "一般設定 - Frigate", "general": "一般設定 - Frigate",
"frigatePlus": "Frigate+ 設定 - Frigate", "frigatePlus": "Frigate+ 設定 - Frigate",
"notifications": "通知設定 - Frigate" "notifications": "通知設定 - Frigate",
"cameraManagement": "カメラ設定 - Frigate",
"cameraReview": "カメラレビュー設定 - Frigate"
}, },
"menu": { "menu": {
"ui": "UI", "ui": "UI",
"enrichments": "エンリッチメント", "enrichments": "高度解析",
"cameras": "カメラ設定", "cameras": "カメラ設定",
"masksAndZones": "マスク/ゾーン", "masksAndZones": "マスク/ゾーン",
"motionTuner": "モーションチューナー", "motionTuner": "モーションチューナー",
@ -21,7 +23,10 @@
"debug": "デバッグ", "debug": "デバッグ",
"users": "ユーザー", "users": "ユーザー",
"notifications": "通知", "notifications": "通知",
"frigateplus": "Frigate+" "frigateplus": "Frigate+",
"cameraManagement": "管理",
"cameraReview": "レビュー",
"roles": "区分"
}, },
"dialog": { "dialog": {
"unsavedChanges": { "unsavedChanges": {
@ -84,8 +89,8 @@
} }
}, },
"enrichments": { "enrichments": {
"title": "エンリッチメント設定", "title": "高度解析設定",
"unsavedChanges": "未保存のエンリッチメント設定の変更", "unsavedChanges": "未保存の高度解析設定の変更",
"birdClassification": { "birdClassification": {
"title": "鳥類分類", "title": "鳥類分類",
"desc": "量子化された TensorFlow モデルを使って既知の鳥を識別します。既知の鳥を認識した場合、その一般名を sub_label として追加します。この情報は UI、フィルタ、通知に含まれます。" "desc": "量子化された TensorFlow モデルを使って既知の鳥を識別します。既知の鳥を認識した場合、その一般名を sub_label として追加します。この情報は UI、フィルタ、通知に含まれます。"
@ -136,9 +141,9 @@
"title": "ナンバープレート認識", "title": "ナンバープレート認識",
"desc": "車両のナンバープレートを認識し、検出文字列を recognized_license_plate フィールドへ、または既知の名称を car タイプのオブジェクトの sub_label として自動追加できます。一般的な用途として、私道に入ってくる車や道路を通過する車のナンバー読み取りがあります。" "desc": "車両のナンバープレートを認識し、検出文字列を recognized_license_plate フィールドへ、または既知の名称を car タイプのオブジェクトの sub_label として自動追加できます。一般的な用途として、私道に入ってくる車や道路を通過する車のナンバー読み取りがあります。"
}, },
"restart_required": "再起動が必要です(エンリッチメント設定を変更)", "restart_required": "再起動が必要です(高度解析設定を変更)",
"toast": { "toast": {
"success": "エンリッチメント設定を保存しました。変更を適用するには Frigate を再起動してください。", "success": "高度解析設定を保存しました。変更を適用するには Frigate を再起動してください。",
"error": "設定変更の保存に失敗しました: {{errorMessage}}" "error": "設定変更の保存に失敗しました: {{errorMessage}}"
} }
}, },
@ -793,6 +798,11 @@
"error": { "error": {
"min": "少なくとも1つのアクションを選択してください。" "min": "少なくとも1つのアクションを選択してください。"
} }
},
"friendly_name": {
"title": "表示名",
"placeholder": "このトリガーの名前または説明",
"description": "このトリガーの表示名または説明文"
} }
} }
}, },
@ -807,6 +817,227 @@
"updateTriggerFailed": "トリガーの更新に失敗しました: {{errorMessage}}", "updateTriggerFailed": "トリガーの更新に失敗しました: {{errorMessage}}",
"deleteTriggerFailed": "トリガーの削除に失敗しました: {{errorMessage}}" "deleteTriggerFailed": "トリガーの削除に失敗しました: {{errorMessage}}"
} }
},
"semanticSearch": {
"desc": "トリガーを使用するにはセマンティック検索を有効にする必要があります。",
"title": "セマンティック検索が無効です"
}
},
"cameraWizard": {
"step3": {
"saveAndApply": "新しいカメラを保存",
"description": "保存前の最終検証と解析。保存する前に各ストリームを接続してください。",
"validationTitle": "ストリーム検証",
"connectAllStreams": "すべてのストリームを接続",
"reconnectionSuccess": "再接続に成功しました。",
"reconnectionPartial": "一部のストリームの再接続に失敗しました。",
"streamUnavailable": "ストリームプレビューは利用できません",
"reload": "再読み込み",
"connecting": "接続中…",
"streamTitle": "ストリーム {{number}}",
"valid": "有効",
"failed": "失敗",
"notTested": "未テスト",
"connectStream": "接続",
"connectingStream": "接続中",
"disconnectStream": "切断",
"estimatedBandwidth": "推定帯域幅",
"roles": "ロール",
"none": "なし",
"error": "エラー",
"streamValidated": "ストリーム {{number}} の検証に成功しました",
"streamValidationFailed": "ストリーム {{number}} の検証に失敗しました",
"saveError": "無効な構成です。設定を確認してください。",
"issues": {
"title": "ストリーム検証",
"videoCodecGood": "ビデオコーデックは {{codec}} です。",
"audioCodecGood": "オーディオコーデックは {{codec}} です。",
"noAudioWarning": "このストリームでは音声が検出されません。録画には音声が含まれません。",
"audioCodecRecordError": "録画に音声を含めるには AAC オーディオコーデックが必要です。",
"audioCodecRequired": "音声検出を有効にするには音声ストリームが必要です。",
"restreamingWarning": "録画ストリームでカメラへの接続数を減らすと、CPU 使用率がわずかに増加する場合があります。",
"hikvision": {
"substreamWarning": "サブストリーム1は低解像度に固定されています。多くの Hikvision 製カメラでは、追加のサブストリームが利用可能であり、カメラ本体の設定で有効化する必要があります。使用できる場合は、それらのストリームを確認して活用することを推奨します。"
},
"dahua": {
"substreamWarning": "サブストリーム1は低解像度に固定されています。多くの DahuaAmcrestEmpireTech 製カメラでは、追加のサブストリームが利用可能であり、カメラ本体の設定で有効化する必要があります。使用できる場合は、それらのストリームを確認して活用することを推奨します。"
}
}
},
"title": "カメラを追加",
"description": "以下の手順に従って、Frigate に新しいカメラを追加します。",
"steps": {
"nameAndConnection": "名称と接続",
"streamConfiguration": "ストリーム設定",
"validationAndTesting": "検証とテスト"
},
"save": {
"success": "新しいカメラ {{cameraName}} を保存しました。",
"failure": "保存エラー: {{cameraName}}。"
},
"testResultLabels": {
"resolution": "解像度",
"video": "ビデオ",
"audio": "オーディオ",
"fps": "FPS"
},
"commonErrors": {
"noUrl": "有効なストリーム URL を入力してください",
"testFailed": "ストリームテストに失敗しました: {{error}}"
},
"step1": {
"description": "カメラの詳細を入力し、接続テストを実行します。",
"cameraName": "カメラ名",
"cameraNamePlaceholder": "例: front_door または Back Yard Overview",
"host": "ホストIP アドレス",
"port": "ポート",
"username": "ユーザー名",
"usernamePlaceholder": "任意",
"password": "パスワード",
"passwordPlaceholder": "任意",
"selectTransport": "トランスポートプロトコルを選択",
"cameraBrand": "カメラブランド",
"selectBrand": "URL テンプレート用のカメラブランドを選択",
"customUrl": "カスタムストリーム URL",
"brandInformation": "ブランド情報",
"brandUrlFormat": "RTSP URL 形式が {{exampleUrl}} のカメラ向け",
"customUrlPlaceholder": "rtsp://username:password@host:port/path",
"testConnection": "接続テスト",
"testSuccess": "接続テストに成功しました!",
"testFailed": "接続テストに失敗しました。入力内容を確認して再試行してください。",
"streamDetails": "ストリーム詳細",
"warnings": {
"noSnapshot": "設定されたストリームからスナップショットを取得できません。"
},
"errors": {
"brandOrCustomUrlRequired": "ホストIP とブランドを選択するか、「その他」を選んでカスタム URL を指定してください",
"nameRequired": "カメラ名は必須です",
"nameLength": "カメラ名は64文字以下である必要があります",
"invalidCharacters": "カメラ名に無効な文字が含まれています",
"nameExists": "このカメラ名は既に存在します",
"brands": {
"reolink-rtsp": "Reolink の RTSP は推奨されません。カメラ設定で http を有効にし、カメラウィザードを再起動することを推奨します。"
}
},
"docs": {
"reolink": "https://docs.frigate.video/configuration/camera_specific.html#reolink-cameras"
}
},
"step2": {
"description": "ストリームのロールを設定し、必要に応じて追加ストリームを登録します。",
"streamsTitle": "カメラストリーム",
"addStream": "ストリームを追加",
"addAnotherStream": "ストリームをさらに追加",
"streamTitle": "ストリーム {{number}}",
"streamUrl": "ストリーム URL",
"streamUrlPlaceholder": "rtsp://username:password@host:port/path",
"url": "URL",
"resolution": "解像度",
"selectResolution": "解像度を選択",
"quality": "品質",
"selectQuality": "品質を選択",
"roles": "ロール",
"roleLabels": {
"detect": "物体検出",
"record": "録画",
"audio": "音声"
},
"testStream": "接続テスト",
"testSuccess": "ストリームテストに成功しました!",
"testFailed": "ストリームテストに失敗しました",
"testFailedTitle": "テスト失敗",
"connected": "接続済み",
"notConnected": "未接続",
"featuresTitle": "機能",
"go2rtc": "カメラへの接続数を削減",
"detectRoleWarning": "\"detect\" ロールを持つストリームが少なくとも1つ必要です。",
"rolesPopover": {
"title": "ストリームロール",
"detect": "物体検出のメインフィード。",
"record": "設定に基づいて映像フィードのセグメントを保存します。",
"audio": "音声検出用のフィード。"
},
"featuresPopover": {
"title": "ストリーム機能",
"description": "go2rtc のリストリーミングを使用してカメラへの接続数を削減します。"
}
}
},
"cameraManagement": {
"title": "カメラ管理",
"addCamera": "新しいカメラを追加",
"editCamera": "カメラを編集:",
"selectCamera": "カメラを選択",
"backToSettings": "カメラ設定に戻る",
"streams": {
"title": "カメラの有効化/無効化",
"desc": "Frigate を再起動するまで一時的にカメラを無効化します。無効化すると、このカメラのストリーム処理は完全に停止し、検出・録画・デバッグは利用できません。<br /> <em>注: これは go2rtc のリストリームを無効にはしません。</em>"
},
"cameraConfig": {
"add": "カメラを追加",
"edit": "カメラを編集",
"description": "ストリーム入力とロールを含むカメラ設定を構成します。",
"name": "カメラ名",
"nameRequired": "カメラ名は必須です",
"nameLength": "カメラ名は64文字未満である必要があります。",
"namePlaceholder": "例: front_door または Back Yard Overview",
"enabled": "有効",
"ffmpeg": {
"inputs": "入力ストリーム",
"path": "ストリームパス",
"pathRequired": "ストリームパスは必須です",
"pathPlaceholder": "rtsp://...",
"roles": "ロール",
"rolesRequired": "少なくとも1つのロールが必要です",
"rolesUnique": "各ロールaudio、detect、recordは1つのストリームにのみ割り当て可能です",
"addInput": "入力ストリームを追加",
"removeInput": "入力ストリームを削除",
"inputsRequired": "少なくとも1つの入力ストリームが必要です"
},
"go2rtcStreams": "go2rtc ストリーム",
"streamUrls": "ストリーム URL",
"addUrl": "URL を追加",
"addGo2rtcStream": "go2rtc ストリームを追加",
"toast": {
"success": "カメラ {{cameraName}} を保存しました"
}
}
},
"cameraReview": {
"title": "カメラレビュー設定",
"object_descriptions": {
"title": "生成AIによるオブジェクト説明",
"desc": "このカメラに対する生成AIのオブジェクト説明を一時的に有効無効にします。無効にすると、このカメラの追跡オブジェクトについてAI生成の説明は要求されません。"
},
"review_descriptions": {
"title": "生成AIによるレビュー説明",
"desc": "このカメラに対する生成AIのレビュー説明を一時的に有効無効にします。無効にすると、このカメラのレビュー項目についてAI生成の説明は要求されません。"
},
"review": {
"title": "レビュー",
"desc": "Frigate を再起動するまで、このカメラのアラートと検出を一時的に有効/無効にします。無効にすると、新しいレビュー項目は生成されません。 ",
"alerts": "アラート ",
"detections": "検出 "
},
"reviewClassification": {
"title": "レビュー分類",
"desc": "Frigate はレビュー項目をアラートと検出に分類します。既定では、すべての <em>person</em> と <em>car</em> オブジェクトはアラートとして扱われます。必須ゾーンを設定することで、分類をより細かく調整できます。",
"noDefinedZones": "このカメラにはゾーンが定義されていません。",
"objectAlertsTips": "すべての {{alertsLabels}} オブジェクトは {{cameraName}} でアラートとして表示されます。",
"zoneObjectAlertsTips": "{{cameraName}} の {{zone}} で検出されたすべての {{alertsLabels}} オブジェクトはアラートとして表示されます。",
"objectDetectionsTips": "{{cameraName}} で分類されていないすべての {{detectionsLabels}} オブジェクトは、どのゾーンにあっても検出として表示されます。",
"zoneObjectDetectionsTips": {
"text": "{{cameraName}} の {{zone}} で分類されていないすべての {{detectionsLabels}} オブジェクトは検出として表示されます。",
"notSelectDetections": "{{cameraName}} の {{zone}} で検出され、アラートに分類されなかったすべての {{detectionsLabels}} オブジェクトは、ゾーンに関係なく検出として表示されます。",
"regardlessOfZoneObjectDetectionsTips": "{{cameraName}} で分類されていないすべての {{detectionsLabels}} オブジェクトは、どのゾーンにあっても検出として表示されます。"
},
"unsavedChanges": "未保存のレビュー分類設定({{camera}}",
"selectAlertsZones": "アラート用のゾーンを選択",
"selectDetectionsZones": "検出用のゾーンを選択",
"limitDetections": "特定のゾーンに検出を限定する",
"toast": {
"success": "レビュー分類の設定を保存しました。変更を適用するには Frigate を再起動してください。"
}
} }
} }
} }

View File

@ -3,7 +3,7 @@
"cameras": "カメラ統計 - Frigate", "cameras": "カメラ統計 - Frigate",
"general": "一般統計 - Frigate", "general": "一般統計 - Frigate",
"storage": "ストレージ統計 - Frigate", "storage": "ストレージ統計 - Frigate",
"enrichments": "エンリッチメント統計 - Frigate", "enrichments": "高度解析統計 - Frigate",
"logs": { "logs": {
"frigate": "Frigate ログ - Frigate", "frigate": "Frigate ログ - Frigate",
"go2rtc": "Go2RTC ログ - Frigate", "go2rtc": "Go2RTC ログ - Frigate",
@ -38,7 +38,7 @@
"general": { "general": {
"title": "全般", "title": "全般",
"detector": { "detector": {
"title": "ディテクタ", "title": "検出器",
"inferenceSpeed": "ディテクタ推論速度", "inferenceSpeed": "ディテクタ推論速度",
"temperature": "ディテクタ温度", "temperature": "ディテクタ温度",
"cpuUsage": "ディテクタの CPU 使用率", "cpuUsage": "ディテクタの CPU 使用率",
@ -167,7 +167,7 @@
"shmTooLow": "/dev/shm の割り当て({{total}} MBは少なくとも {{min}} MB に増やす必要があります。" "shmTooLow": "/dev/shm の割り当て({{total}} MBは少なくとも {{min}} MB に増やす必要があります。"
}, },
"enrichments": { "enrichments": {
"title": "エンリッチメント", "title": "高度解析",
"infPerSecond": "毎秒推論回数", "infPerSecond": "毎秒推論回数",
"embeddings": { "embeddings": {
"image_embedding": "画像埋め込み", "image_embedding": "画像埋め込み",

View File

@ -1,9 +1,9 @@
{ {
"crying": "울음", "crying": "울음",
"snoring": "코골이", "snoring": "코골이",
"singing": "노래하기", "singing": "노래",
"yell": "비명", "yell": "비명",
"speech": "발표", "speech": "말소리",
"babbling": "옹알이", "babbling": "옹알이",
"bicycle": "자전거", "bicycle": "자전거",
"a_capella": "아카펠라", "a_capella": "아카펠라",
@ -11,5 +11,62 @@
"accordion": "아코디언", "accordion": "아코디언",
"acoustic_guitar": "어쿠스틱 기타", "acoustic_guitar": "어쿠스틱 기타",
"car": "차량", "car": "차량",
"motorcycle": "원동기" "motorcycle": "원동기",
"bus": "버스",
"train": "기차",
"boat": "보트",
"bird": "새",
"cat": "고양이",
"dog": "강아지",
"horse": "말",
"sheep": "양",
"skateboard": "스케이트보드",
"door": "문",
"mouse": "마우스",
"keyboard": "키보드",
"sink": "싱크대",
"blender": "블렌더",
"clock": "벽시계",
"scissors": "가위",
"hair_dryer": "헤어 드라이어",
"toothbrush": "칫솔",
"vehicle": "탈 것",
"animal": "동물",
"bark": "개",
"goat": "염소",
"bellow": "포효",
"whoop": "환성",
"whispering": "속삭임",
"laughter": "웃음",
"snicker": "낄낄 웃음",
"sigh": "한숨",
"choir": "합창",
"yodeling": "요들링",
"chant": "성가",
"mantra": "만트라",
"child_singing": "어린이 노래",
"synthetic_singing": "Synthetic Singing",
"rapping": "랩",
"humming": "허밍",
"groan": "신음",
"grunt": "으르렁",
"whistling": "휘파람",
"breathing": "숨쉬는 소리",
"wheeze": "헐떡임",
"gasp": "헐떡임",
"pant": "거친숨",
"snort": "코골이",
"cough": "기침",
"throat_clearing": "목 긁는 소리",
"sneeze": "재채기",
"sniff": "훌쩍",
"run": "달리기",
"shuffle": "Shuffle",
"footsteps": "발소리",
"chewing": "씹는 소리",
"biting": "치는 소리",
"gargling": "가글",
"stomach_rumble": "배 꼬르륵",
"burping": "트림",
"camera": "카메라"
} }

View File

@ -10,18 +10,262 @@
"30minutes": "30분", "30minutes": "30분",
"5minutes": "5분", "5minutes": "5분",
"untilRestart": "재시작 될 때까지", "untilRestart": "재시작 될 때까지",
"ago": "{{timeAgo}} 전" "ago": "{{timeAgo}} 전",
"justNow": "지금 막",
"today": "오늘",
"yesterday": "어제",
"last7": "최근 7일",
"last14": "최근 14일",
"last30": "최근 30일",
"thisWeek": "이번 주",
"lastWeek": "저번 주",
"thisMonth": "이번 달",
"lastMonth": "저번 달",
"pm": "오후",
"am": "오전",
"yr": "{{time}}년",
"year_other": "{{time}} 년",
"mo": "{{time}}월",
"month_other": "{{time}} 월",
"d": "{{time}}일",
"day_other": "{{time}} 일",
"h": "{{time}}시",
"hour_other": "{{time}} 시",
"m": "{{time}}분",
"minute_other": "{{time}} 분",
"s": "{{time}}초",
"second_other": "{{time}} 초",
"formattedTimestamp": {
"12hour": "MMM d, h:mm:ss aaa",
"24hour": "MMM d, HH:mm:ss"
},
"formattedTimestamp2": {
"12hour": "MM/dd h:mm:ssa",
"24hour": "d MMM HH:mm:ss"
},
"formattedTimestampHourMinute": {
"12hour": "h:mm aaa",
"24hour": "HH:mm"
},
"formattedTimestampHourMinuteSecond": {
"12hour": "h:mm:ss aaa",
"24hour": "HH:mm:ss"
},
"formattedTimestampMonthDayHourMinute": {
"12hour": "MMM d, h:mm aaa",
"24hour": "MMM d, HH:mm"
},
"formattedTimestampMonthDayYear": {
"12hour": "MMM d, yyyy",
"24hour": "MMM d, yyyy"
},
"formattedTimestampMonthDayYearHourMinute": {
"12hour": "MMM d yyyy, h:mm aaa",
"24hour": "MMM d yyyy, HH:mm"
},
"formattedTimestampMonthDay": "MMM d",
"formattedTimestampFilename": {
"12hour": "MM-dd-yy-h-mm-ss-a",
"24hour": "MM-dd-yy-HH-mm-ss"
}
}, },
"notFound": { "notFound": {
"title": "404" "title": "404",
"documentTitle": "찾을 수 없음 - Frigate",
"desc": "페이지 찾을 수 없음"
}, },
"accessDenied": { "accessDenied": {
"title": "접근 거부", "title": "접근 거부",
"documentTitle": "접근 거부 - Frigate" "documentTitle": "접근 거부 - Frigate",
"desc": "이 페이지 접근 권한이 없습니다."
}, },
"menu": { "menu": {
"user": { "user": {
"account": "계정" "account": "계정",
"title": "사용자",
"current": "현재 사용자:{{user}}",
"anonymous": "익명",
"logout": "로그아웃",
"setPassword": "비밀번호 설정"
},
"system": "시스템",
"systemMetrics": "시스템 지표",
"configuration": "설정",
"systemLogs": "시스템 로그",
"settings": "설정",
"configurationEditor": "설정 편집기",
"languages": "언어",
"language": {
"en": "English (English)",
"es": "Español (Spanish)",
"zhCN": "简体中文 (Simplified Chinese)",
"hi": "हिन्दी (Hindi)",
"fr": "Français (French)",
"ar": "العربية (Arabic)",
"pt": "Português (Portuguese)",
"ptBR": "Português brasileiro (Brazilian Portuguese)",
"ru": "Русский (Russian)",
"de": "Deutsch (German)",
"ja": "日本語 (Japanese)",
"tr": "Türkçe (Turkish)",
"it": "Italiano (Italian)",
"nl": "Nederlands (Dutch)",
"sv": "Svenska (Swedish)",
"cs": "Čeština (Czech)",
"nb": "Norsk Bokmål (Norwegian Bokmål)",
"ko": "한국어 (Korean)",
"vi": "Tiếng Việt (Vietnamese)",
"fa": "فارسی (Persian)",
"pl": "Polski (Polish)",
"uk": "Українська (Ukrainian)",
"he": "עברית (Hebrew)",
"el": "Ελληνικά (Greek)",
"ro": "Română (Romanian)",
"hu": "Magyar (Hungarian)",
"fi": "Suomi (Finnish)",
"da": "Dansk (Danish)",
"sk": "Slovenčina (Slovak)",
"yue": "粵語 (Cantonese)",
"th": "ไทย (Thai)",
"ca": "Català (Catalan)",
"sr": "Српски (Serbian)",
"sl": "Slovenščina (Slovenian)",
"lt": "Lietuvių (Lithuanian)",
"bg": "Български (Bulgarian)",
"gl": "Galego (Galician)",
"id": "Bahasa Indonesia (Indonesian)",
"ur": "اردو (Urdu)",
"withSystem": {
"label": "시스템 설정 언어 사용"
}
},
"appearance": "화면 설정",
"darkMode": {
"label": "다크 모드",
"light": "라이트",
"dark": "다크",
"withSystem": {
"label": "시스템 설정에 따라 설정"
}
},
"withSystem": "시스템",
"theme": {
"label": "테마",
"blue": "파랑",
"green": "녹색",
"nord": "노드 (Nord)",
"red": "빨강",
"highcontrast": "고 대비",
"default": "기본값"
},
"help": "도움말",
"documentation": {
"title": "문서",
"label": "Frigate 문서"
},
"restart": "Frigate 재시작",
"live": {
"title": "실시간",
"allCameras": "모든 카메라",
"cameras": {
"title": "카메라",
"count_other": "{{count}} 카메라"
}
},
"review": "다시보기",
"explore": "탐색",
"export": "내보내기",
"uiPlayground": "UI 실험장",
"faceLibrary": "얼굴 라이브러리"
},
"unit": {
"speed": {
"mph": "mph",
"kph": "km/h"
},
"length": {
"feet": "피트",
"meters": "미터"
},
"data": {
"kbps": "kB/s",
"mbps": "MB/s",
"gbps": "GB/s",
"kbph": "kB/hour",
"mbph": "MB/hour",
"gbph": "GB/hour"
} }
},
"label": {
"back": "뒤로"
},
"button": {
"apply": "적용",
"reset": "리셋",
"done": "완료",
"enabled": "활성화됨",
"enable": "활성화",
"disabled": "비활성화됨",
"disable": "비활성화",
"save": "저장",
"saving": "저장 중…",
"cancel": "취소",
"close": "닫기",
"copy": "복사",
"back": "뒤로",
"history": "히스토리",
"fullscreen": "전체화면",
"exitFullscreen": "전체화면 나가기",
"pictureInPicture": "Picture in Picture",
"twoWayTalk": "양방향 말하기",
"cameraAudio": "카메라 오디오",
"on": "켜기",
"off": "끄기",
"edit": "편집",
"copyCoordinates": "코디네이트 복사",
"delete": "삭제",
"yes": "예",
"no": "아니오",
"download": "다운로드",
"info": "정보",
"suspended": "일시 정지됨",
"unsuspended": "재개",
"play": "재생",
"unselect": "선택 해제",
"export": "내보내기",
"deleteNow": "바로 삭제하기",
"next": "다음"
},
"toast": {
"copyUrlToClipboard": "클립보드에 URL이 복사되었습니다.",
"save": {
"title": "저장",
"error": {
"title": "설정 저장 실패: {{errorMessage}}",
"noMessage": "설정 저장이 실패했습니다"
}
}
},
"role": {
"title": "역할",
"admin": "관리자",
"viewer": "감시자",
"desc": "관리자는 Frigate UI에 모든 접근 권한이 있습니다. 감시자는 카메라 감시, 돌아보기, 과거 영상 조회만 가능합니다."
},
"pagination": {
"label": "나눠보기",
"previous": {
"title": "이전",
"label": "이전 페이지"
},
"next": {
"title": "다음",
"label": "다음 페이지"
},
"more": "더 많은 페이지"
},
"selectItem": "{{item}} 선택",
"information": {
"pixels": "{{area}}px"
} }
} }

View File

@ -1,11 +1,11 @@
{ {
"form": { "form": {
"user": "사용자명", "user": "사용자명",
"password": "패스워드", "password": "비밀번호",
"login": "로그인", "login": "로그인",
"errors": { "errors": {
"usernameRequired": "사용자명은 필수입니다", "usernameRequired": "사용자명은 필수입니다",
"passwordRequired": "패스워드는 필수입니다", "passwordRequired": "비밀번호는 필수입니다",
"rateLimit": "너무 많이 시도했습니다. 다음에 다시 시도하세요.", "rateLimit": "너무 많이 시도했습니다. 다음에 다시 시도하세요.",
"loginFailed": "로그인 실패", "loginFailed": "로그인 실패",
"unknownError": "알려지지 않은 에러. 로그를 확인하세요.", "unknownError": "알려지지 않은 에러. 로그를 확인하세요.",

View File

@ -4,7 +4,83 @@
"add": "카메라 그룹 추가", "add": "카메라 그룹 추가",
"edit": "카메라 그룹 편집", "edit": "카메라 그룹 편집",
"delete": { "delete": {
"label": "카메라 그룹 삭제" "label": "카메라 그룹 삭제",
"confirm": {
"title": "삭제 확인",
"desc": "정말로 카메라 그룹을 삭제하시겠습니까 <em>{{name}}</em>?"
}
},
"name": {
"label": "이름",
"placeholder": "이름을 입력하세요…",
"errorMessage": {
"mustLeastCharacters": "카메라 그룹 이름은 최소 2자 이상 써야합니다.",
"exists": "이미 존재하는 카메라 그룹 이름입니다.",
"nameMustNotPeriod": "카메라 그룹 이름에 마침표(.)를 넣을 수 없습니다.",
"invalid": "설정 불가능한 카메라 그룹 이름."
}
},
"cameras": {
"label": "카메라",
"desc": "이 그룹에 넣을 카메라 선택하기."
},
"icon": "아이콘",
"success": "카메라 그룹 {{name}} 저장되었습니다.",
"camera": {
"birdseye": "버드아이",
"setting": {
"label": "카메라 스트리밍 설정",
"title": "{{cameraName}} 스트리밍 설정",
"desc": "카메라 그룹 대시보드의 실시간 스트리밍 옵션을 변경하세요. <em>이 설정은 기기/브라우저에 따라 다릅니다.</em>",
"audioIsAvailable": "이 카메라는 오디오 기능을 사용할 수 있습니다",
"audioIsUnavailable": "이 카메라는 오디오 기능을 사용할 수 없습니다",
"audio": {
"tips": {
"title": "오디오를 출력하려면 카메라가 지원하거나 go2rtc에서 설정해야합니다."
}
},
"stream": "스트림",
"placeholder": "스트림 선택",
"streamMethod": {
"label": "스트리밍 방식",
"placeholder": "스트리밍 방식 선택",
"method": {
"noStreaming": {
"label": "스트리밍 없음",
"desc": "카메라 이미지는 1분에 한 번만 보여지며 라이브 스트리밍은 되지 않습니다."
},
"smartStreaming": {
"label": "스마트 스트리밍 (추천함)",
"desc": "스마트 스트리밍은 감지되는 활동이 없을 때 대역폭과 자원을 절약하기 위해 1분마다 한 번 카메라 이미지를 업데이트합니다. 활동이 감지되면, 이미지는 자동으로 라이브 스트림으로 원활하게 전환됩니다."
},
"continuousStreaming": {
"label": "지속적인 스트리밍",
"desc": {
"title": "활동이 감지되지 않더라도 카메라 이미지가 대시보드에서 항상 실시간 스트림됩니다.",
"warning": "지속적인 스트리밍은 높은 대역폭 사용과 퍼포먼스 이슈를 발생할 수 있습니다. 사용에 주의해주세요."
}
}
}
},
"compatibilityMode": {
"label": "호환 모드",
"desc": "이 옵션은 카메라 라이브 스트림 화면의 색상이 왜곡 되었거나 이미지 오른쪽에 대각선이 나타날때만 사용하세요."
}
}
} }
},
"debug": {
"options": {
"label": "설정",
"title": "옵션",
"showOptions": "옵션 보기",
"hideOptions": "옵션 숨기기"
},
"boundingBox": "감지 영역 상자",
"timestamp": "시간 기록",
"zones": "구역 (Zones)",
"mask": "마스크",
"motion": "움직임",
"regions": "영역 (Regions)"
} }
} }

View File

@ -1,10 +1,92 @@
{ {
"restart": { "restart": {
"title": "Frigate 정말로 다시 시작할까요?", "title": "Frigate 정말로 다시 시작할까요?",
"button": "재시작", "button": "재시작",
"restarting": { "restarting": {
"title": "Frigate가 재시작 중입니다", "title": "Frigate이 재시작 중입니다",
"content": "이 페이지는 {{countdown}} 뒤에 새로 고침 됩니다." "content": "이 페이지는 {{countdown}} 뒤에 새로 고침 됩니다.",
"button": "강제 재시작"
}
},
"explore": {
"plus": {
"submitToPlus": {
"label": "Frigate+에 등록하기"
},
"review": {
"question": {
"label": "Frigate +에 이 레이블 등록하기"
}
}
},
"video": {
"viewInHistory": "히스토리 보기"
}
},
"export": {
"time": {
"fromTimeline": "타임라인에서 선택하기",
"lastHour_other": "지난 시간",
"custom": "커스텀",
"start": {
"title": "시작 시간",
"label": "시작 시간 선택"
},
"end": {
"title": "종료 시간",
"label": "종료 시간 선택"
}
},
"name": {
"placeholder": "내보내기 이름"
},
"select": "선택",
"export": "내보내기",
"selectOrExport": "선택 또는 내보내기",
"toast": {
"success": "내보내기가 성공적으로 시작되었습니다. /exports 폴더에서 파일을 보실 수 있습니다.",
"error": {
"failed": "내보내기 시작 실패:{{error}}",
"endTimeMustAfterStartTime": "종료 시간은 시작 시간보다 뒤에 있어야합니다",
"noVaildTimeSelected": "유효한 시간 범위가 선택되지 않았습니다"
}
},
"fromTimeline": {
"saveExport": "내보내기 저장",
"previewExport": "내보내기 미리보기"
}
},
"streaming": {
"label": "스트림",
"restreaming": {
"disabled": "이 카메라는 재 스트리밍이 되지 않습니다.",
"desc": {
"title": "이 카메라를 위해 추가적인 라이브 뷰 옵션과 오디오를 go2rtc에서 설정하세요."
}
},
"showStats": {
"label": "스트림 통계 보기",
"desc": "이 옵션을 활성화하면 스트림 통계가 카메라 피드에 나타납니다."
},
"debugView": "디버그 뷰"
},
"search": {
"saveSearch": {
"label": "검색 저장",
"desc": "저장된 검색에 이름을 지정해주세요.",
"placeholder": "검색에 이름 입력하기",
"overwrite": "{{searchName}} (이/가) 이미 존재합니다. 값을 덮어 씌웁니다.",
"success": "{{searchName}} 검색이 저장되었습니다.",
"button": {
"save": {
"label": "이 검색 저장하기"
}
}
}
},
"recording": {
"confirmDelete": {
"title": "삭제 확인"
} }
} }
} }

View File

@ -1,3 +1,39 @@
{ {
"filter": "필터" "filter": "필터",
"labels": {
"label": "레이블",
"all": {
"title": "모든 레이블",
"short": "레이블"
}
},
"zones": {
"label": "구역",
"all": {
"title": "모든 구역",
"short": "구역"
}
},
"dates": {
"selectPreset": "프리셋 선택",
"all": {
"title": "모든 날짜",
"short": "날짜"
}
},
"timeRange": "시간 구역",
"subLabels": {
"label": "서브 레이블",
"all": "모든 서브 레이블"
},
"more": "더 많은 필터",
"classes": {
"label": "분류",
"all": {
"title": "모든 분류"
}
},
"reset": {
"label": "기본값으로 필터 초기화"
}
} }

View File

@ -3,7 +3,7 @@
"downloadVideo": { "downloadVideo": {
"label": "비디오 다운로드", "label": "비디오 다운로드",
"toast": { "toast": {
"success": "선택한 비디오들의 다운로드가 시작되었습니다." "success": "다시보기 항목 다운로드가 시작되었습니다."
} }
} }
} }

View File

@ -1,7 +1,7 @@
{ {
"submitFrigatePlus": { "submitFrigatePlus": {
"submit": "제출", "submit": "제출",
"title": "이 프레임을 Frigate+로 전송하시겠습니까?" "title": "이 프레임을 Frigate+에 제출하시겠습니까?"
}, },
"stats": { "stats": {
"bandwidth": { "bandwidth": {
@ -10,17 +10,42 @@
}, },
"latency": { "latency": {
"short": { "short": {
"title": "지연" "title": "지연",
"value": "{{seconds}} 초"
}, },
"title": "지연:" "title": "지연:",
"value": "{{seconds}} 초"
}, },
"streamType": { "streamType": {
"short": "종류", "short": "종류",
"title": "스트림 종류:" "title": "스트림 종류:"
}, },
"totalFrames": "총 프레임:" "totalFrames": "총 프레임:",
"droppedFrames": {
"title": "손실 프레임:",
"short": {
"title": "손실됨",
"value": "{{droppedFrames}} 프레임"
}
},
"decodedFrames": "복원된 프레임:",
"droppedFrameRate": "프레임 손실률:"
}, },
"noRecordingsFoundForThisTime": "이 시간에는 녹화본이 없습니다", "noRecordingsFoundForThisTime": "이 시간대에는 녹화본이 없습니다",
"noPreviewFound": "미리 보기가 없습니다", "noPreviewFound": "미리 보기를 찾을 수 없습니다",
"noPreviewFoundFor": "{{cameraName}}에 미리보기가 없습니다" "noPreviewFoundFor": "{{cameraName}}에 미리보기를 찾을 수 없습니다",
"livePlayerRequiredIOSVersion": "이 라이브 스트림 방식은 iOS 17.1 이거나 높은 버전이 필요합니다.",
"streamOffline": {
"title": "스트림 오프라인",
"desc": "{{cameraName}} 카메라에 <code>감지(detect)</code> 스트림의 프레임을 얻지 못했습니다. 에러 로그를 확인하세요"
},
"cameraDisabled": "카메라를 이용할 수 없습니다",
"toast": {
"success": {
"submittedFrigatePlus": "Frigate+에 프레임이 성공적으로 제출됐습니다"
},
"error": {
"submitFrigatePlusFailed": "Frigate+에 프레임을 보내지 못했습니다"
}
}
} }

View File

@ -2,5 +2,119 @@
"person": "사람", "person": "사람",
"bicycle": "자전거", "bicycle": "자전거",
"car": "차량", "car": "차량",
"motorcycle": "원동기" "motorcycle": "원동기",
"airplane": "비행기",
"bus": "버스",
"train": "기차",
"boat": "보트",
"traffic_light": "신호등",
"fire_hydrant": "소화전",
"street_sign": "도로 표지판",
"stop_sign": "정지 표지판",
"parking_meter": "주차 요금 정산기",
"bench": "벤치",
"bird": "새",
"cat": "고양이",
"dog": "강아지",
"horse": "말",
"sheep": "양",
"cow": "소",
"elephant": "코끼리",
"bear": "곰",
"zebra": "얼룩말",
"giraffe": "기린",
"hat": "모자",
"backpack": "백팩",
"umbrella": "우산",
"shoe": "신발",
"eye_glasses": "안경",
"handbag": "핸드백",
"tie": "타이",
"suitcase": "슈트케이스",
"frisbee": "프리스비",
"skis": "스키",
"snowboard": "스노우보드",
"sports_ball": "스포츠 볼",
"kite": "연",
"baseball_bat": "야구 방망이",
"baseball_glove": "야구 글로브",
"skateboard": "스케이트보드",
"surfboard": "서핑보드",
"tennis_racket": "테니스 라켓",
"bottle": "병",
"plate": "번호판",
"wine_glass": "와인잔",
"cup": "컵",
"fork": "포크",
"knife": "칼",
"spoon": "숟가락",
"bowl": "보울",
"banana": "바나나",
"apple": "사과",
"sandwich": "샌드위치",
"orange": "오렌지",
"broccoli": "브로콜리",
"carrot": "당근",
"hot_dog": "핫도그",
"pizza": "피자",
"donut": "도넛",
"cake": "케이크",
"chair": "의자",
"couch": "소파",
"potted_plant": "화분",
"bed": "침대",
"mirror": "거울",
"dining_table": "식탁",
"window": "창문",
"desk": "책상",
"toilet": "화장실",
"door": "문",
"tv": "TV",
"laptop": "랩탑",
"mouse": "마우스",
"remote": "리모콘",
"keyboard": "키보드",
"cell_phone": "휴대폰",
"microwave": "전자레인지",
"oven": "오븐",
"toaster": "토스터기",
"sink": "싱크대",
"refrigerator": "냉장고",
"blender": "블렌더",
"book": "책",
"clock": "벽시계",
"vase": "꽃병",
"scissors": "가위",
"teddy_bear": "테디베어",
"hair_dryer": "헤어 드라이어",
"toothbrush": "칫솔",
"hair_brush": "빗",
"vehicle": "탈 것",
"squirrel": "다람쥐",
"deer": "사슴",
"animal": "동물",
"bark": "개",
"fox": "여우",
"goat": "염소",
"rabbit": "토끼",
"raccoon": "라쿤",
"robot_lawnmower": "로봇 잔디깎기",
"waste_bin": "쓰레기통",
"on_demand": "수동",
"face": "얼굴",
"license_plate": "차량 번호판",
"package": "패키지",
"bbq_grill": "바베큐 그릴",
"amazon": "Amazon",
"usps": "USPS",
"ups": "UPS",
"fedex": "FedEx",
"dhl": "DHL",
"an_post": "An Post",
"purolator": "Purolator",
"postnl": "PostNL",
"nzpost": "NZPost",
"postnord": "PostNord",
"gls": "GLS",
"dpd": "DPD"
} }

View File

@ -1,5 +1,18 @@
{ {
"documentTitle": "설정 편집기 - Frigate", "documentTitle": "설정 편집기 - Frigate",
"configEditor": "설정 편집기", "configEditor": "설정 편집기",
"safeConfigEditor": "설정 편집기 (안전 모드)" "safeConfigEditor": "설정 편집기 (안전 모드)",
"safeModeDescription": "설정 오류로 인해 Frigate가 안전 모드로 전환되었습니다.",
"copyConfig": "설정 복사",
"saveAndRestart": "저장 & 재시작",
"saveOnly": "저장만 하기",
"confirm": "저장 없이 나갈까요?",
"toast": {
"success": {
"copyToClipboard": "설정이 클립보드에 저장되었습니다."
},
"error": {
"savingError": "설정 저장 오류"
}
}
} }

View File

@ -1,8 +1,51 @@
{ {
"alerts": "알림", "alerts": "경보",
"detections": "지", "detections": "대상 감지",
"motion": { "motion": {
"label": "움직임", "label": "움직임 감지",
"only": "움직임만" "only": "움직임 감지만"
} },
"allCameras": "모든 카메라",
"empty": {
"alert": "다시 볼 '경보' 영상이 없습니다",
"detection": "다시 볼 '대상 감지' 영상이 없습니다",
"motion": "움직임 감지 데이터가 없습니다"
},
"timeline": "타임라인",
"timeline.aria": "타임라인 선택",
"events": {
"label": "이벤트",
"aria": "이벤트 선택",
"noFoundForTimePeriod": "이 시간대에 이벤트가 없습니다."
},
"detail": {
"noDataFound": "다시 볼 상세 데이터가 없습니다",
"aria": "상세 보기",
"trackedObject_one": "추적 대상",
"trackedObject_other": "추적 대상",
"noObjectDetailData": "상세 보기 데이터가 없습니다."
},
"objectTrack": {
"trackedPoint": "추적 포인트",
"clickToSeek": "이 시점으로 이동"
},
"documentTitle": "다시 보기 - Frigate",
"recordings": {
"documentTitle": "녹화 - Frigate"
},
"calendarFilter": {
"last24Hours": "최근 24시간"
},
"markAsReviewed": "'다시 봤음'으로 표시",
"markTheseItemsAsReviewed": "이 영상들을 '다시 봤음'으로 표시",
"newReviewItems": {
"label": "새로운 '다시 보기' 영상 보기",
"button": "새로운 '다시 보기' 영상"
},
"selected_one": "{{count}} 선택됨",
"selected_other": "{{count}} 선택됨",
"camera": "카메라",
"detected": "감지됨",
"suspiciousActivity": "수상한 행동",
"threateningActivity": "위협적인 행동"
} }

View File

@ -1,4 +1,31 @@
{ {
"documentTitle": "탐색 - Frigate", "documentTitle": "탐색 - Frigate",
"generativeAI": "생성형 AI" "generativeAI": "생성형 AI",
"exploreMore": "{{label}} 더 많은 감지 대상 탐색하기",
"exploreIsUnavailable": {
"title": "탐색을 사용할 수 없습니다",
"embeddingsReindexing": {
"context": "감지 정보 재처리가 완료되면 탐색할 수 있습니다.",
"startingUp": "시작 중…",
"estimatedTime": "예상 남은시간:",
"finishingShortly": "곧 완료됩니다",
"step": {
"thumbnailsEmbedded": "처리된 썸네일: ",
"descriptionsEmbedded": "처리된 설명: ",
"trackedObjectsProcessed": "처리된 추적 감지: "
}
},
"downloadingModels": {
"context": "Frigate가 시맨틱 검색 기능을 지원하기 위해 필요한 임베딩 모델을 다운로드하고 있습니다. 네트워크 연결 속도에 따라 몇 분 정도 소요될 수 있습니다.",
"setup": {
"visionModel": "Vision model",
"visionModelFeatureExtractor": "Vision model feature extractor",
"textModel": "Text model",
"textTokenizer": "Text tokenizer"
}
}
},
"details": {
"timestamp": "시간 기록"
}
} }

View File

@ -2,7 +2,7 @@
"documentTitle": "내보내기 - Frigate", "documentTitle": "내보내기 - Frigate",
"search": "검색", "search": "검색",
"noExports": "내보내기가 없습니다", "noExports": "내보내기가 없습니다",
"deleteExport": "내보내기 ", "deleteExport": "내보내기 제",
"deleteExport.desc": "{{exportName}}을 지우시겠습니까?", "deleteExport.desc": "{{exportName}}을 지우시겠습니까?",
"editExport": { "editExport": {
"title": "내보내기 이름 변경", "title": "내보내기 이름 변경",

View File

@ -1,10 +1,84 @@
{ {
"description": { "description": {
"placeholder": "이 모음집의 이름을 입력해주세요", "placeholder": "이 모음집의 이름을 입력해주세요",
"addFace": "얼굴 라이브러리에 새 컬렉션 추가하는 방법을 단계별로 알아보세요.", "addFace": "얼굴 라이브러리에 새 모음집 추가하는 방법을 단계별로 알아보세요.",
"invalidName": "잘못된 이름입니다. 이름은 문자, 숫자, 공백, 따옴표 ('), 밑줄 (_), 그리고 붙임표 (-)만 포함이 가능합니다." "invalidName": "잘못된 이름입니다. 이름은 문자, 숫자, 공백, 따옴표 ('), 밑줄 (_), 그리고 붙임표 (-)만 포함이 가능합니다."
}, },
"details": { "details": {
"person": "사람" "person": "사람",
"subLabelScore": "보조 레이블 신뢰도",
"face": "얼굴 상세정보",
"timestamp": "시간 기록",
"unknown": "알 수 없음"
},
"selectItem": "{{item}} 선택",
"documentTitle": "얼굴 라이브러리 - Frigate",
"uploadFaceImage": {
"title": "얼굴 사진 올리기"
},
"collections": "모음집",
"createFaceLibrary": {
"title": "모음집 만들기",
"desc": "새로운 모음집 만들기",
"new": "새 얼굴 만들기"
},
"steps": {
"faceName": "얼굴 이름 입력",
"uploadFace": "얼굴 사진 올리기",
"nextSteps": "다음 단계"
},
"train": {
"title": "학습",
"aria": "학습 선택"
},
"selectFace": "얼굴 선택",
"deleteFaceLibrary": {
"title": "이름 삭제"
},
"deleteFaceAttempts": {
"title": "얼굴 삭제"
},
"renameFace": {
"title": "얼굴 이름 바꾸기",
"desc": "{{name}}의 새 이름을 입력하세요"
},
"button": {
"deleteFaceAttempts": "얼굴 삭제",
"addFace": "얼굴 추가",
"renameFace": "얼굴 이름 바꾸기",
"deleteFace": "얼굴 삭제",
"uploadImage": "이미지 올리기",
"reprocessFace": "얼굴 재조정"
},
"imageEntry": {
"validation": {
"selectImage": "이미지 파일을 선택해주세요."
},
"dropActive": "여기에 이미지 놓기…",
"dropInstructions": "이미지를 끌어다 놓거나 여기에 붙여넣으세요. 선택할 수도 있습니다.",
"maxSize": "최대 용량: {{size}}MB"
},
"nofaces": "얼굴을 찾을 수 없습니다",
"pixels": "{{area}}px",
"trainFaceAs": "얼굴을 다음과 같이 훈련하기:",
"trainFace": "얼굴 훈련하기",
"toast": {
"success": {
"uploadedImage": "이미지 업로드에 성공했습니다.",
"addFaceLibrary": "{{name}} 을 성공적으로 얼굴 라이브러리에 추가했습니다!",
"deletedFace_other": "{{count}} 얼굴을 성공적으로 삭제했습니다.",
"renamedFace": "얼굴 이름을 {{name}} 으로 성공적으로 바꿨습니다",
"trainedFace": "얼굴 훈련을 성공적으로 마쳤습니다.",
"updatedFaceScore": "얼굴 신뢰도를 성공적으로 업데이트 했습니다."
},
"error": {
"uploadingImageFailed": "이미지 업로드 실패:{{errorMessage}}",
"addFaceLibraryFailed": "얼굴 이름 설정 실패:{{errorMessage}}",
"deleteFaceFailed": "삭제 실패:{{errorMessage}}",
"deleteNameFailed": "이름 삭제 실패:{{errorMessage}}",
"renameFaceFailed": "이름 바꾸기 실패:{{errorMessage}}",
"trainFailed": "훈련 실패:{{errorMessage}}",
"updateFaceScoreFailed": "얼굴 신뢰도 업데이트 실패:{{errorMessage}}"
}
} }
} }

View File

@ -1,8 +1,183 @@
{ {
"documentTitle": "실시간 - Frigate", "documentTitle": "실시간 보기 - Frigate",
"documentTitle.withCamera": "실시간 - {{camera}} - Frigate", "documentTitle.withCamera": "{{camera}} - 실시간 보기 - Frigate",
"lowBandwidthMode": "저대역폭 모드", "lowBandwidthMode": "저대역폭 모드",
"twoWayTalk": { "twoWayTalk": {
"enable": "양방향 말하기 활성화" "enable": "양방향 말하기 활성화",
"disable": "양방향 말하기 비활성화"
},
"cameraAudio": {
"enable": "카메라 오디오 활성화",
"disable": "카메라 오디오 비활성화"
},
"ptz": {
"move": {
"clickMove": {
"label": "클릭해서 카메라 중앙 배치",
"enable": "클릭해서 움직이기 기능 활성화",
"disable": "클릭해서 움직이기 기능 비활성화"
},
"left": {
"label": "PTZ 카메라 왼쪽으로 이동"
},
"up": {
"label": "PTZ 카메라 위로 이동"
},
"down": {
"label": "PTZ 카메라 아래로 이동"
},
"right": {
"label": "PTZ 카메라 오른쪽으로 이동"
}
},
"zoom": {
"in": {
"label": "PTZ 카메라 확대"
},
"out": {
"label": "PTZ 카메라 축소"
}
},
"focus": {
"in": {
"label": "PTZ 카메라 포커스 인"
},
"out": {
"label": "PTZ 카메라 포커스 아웃"
}
},
"frame": {
"center": {
"label": "클릭해서 PTZ 카메라 중앙 배치"
}
},
"presets": "PTZ 카메라 프리셋"
},
"camera": {
"enable": "카메라 활성화",
"disable": "카메라 비활성화"
},
"muteCameras": {
"enable": "모든 카메라 음소거",
"disable": "모든 카메라 음소거 해제"
},
"detect": {
"enable": "감지 활성화",
"disable": "감지 비활성화"
},
"recording": {
"enable": "녹화 활성화",
"disable": "녹화 비활성화"
},
"snapshots": {
"enable": "스냅샷 활성화",
"disable": "스냅샷 비활성화"
},
"audioDetect": {
"enable": "오디오 감지 활성화",
"disable": "오디오 감지 비활성화"
},
"transcription": {
"enable": "실시간 오디오 자막 활성화",
"disable": "실시간 오디오 자막 비활성화"
},
"autotracking": {
"enable": "자동 추적 활성화",
"disable": "자동 추적 비활성화"
},
"streamStats": {
"enable": "스트림 통계 보기",
"disable": "스트림 통계 숨기기"
},
"manualRecording": {
"title": "수동 녹화",
"tips": "이 카메라의 녹화 보관 설정에 따라 인스턴트 스냅샷을 다운로드하거나 수동 녹화를 시작할 수 있습니다.",
"playInBackground": {
"label": "백그라운드에서 재생",
"desc": "이 옵션을 활성화하면 플레이어가 숨겨져도 계속 스트리밍됩니다."
},
"showStats": {
"label": "통계 보기",
"desc": "이 옵션을 활성화하면 카메라 피드에 스트림 통계가 나타납니다."
},
"debugView": "디버그 보기",
"start": "수동 녹화 시작",
"started": "수동 녹화 시작되었습니다.",
"failedToStart": "수동 녹화 시작이 실패했습니다.",
"recordDisabledTips": "이 카메라 설정에서 녹화가 비활성화 되었거나 제한되어 있어 스냅샷만 저장됩니다.",
"end": "수동 녹화 종료",
"ended": "수동 녹화가 종료되었습니다.",
"failedToEnd": "수동 녹화 종료가 실패했습니다."
},
"streamingSettings": "스트리밍 설정",
"notifications": "알림",
"audio": "오디오",
"suspend": {
"forTime": "일시정지 시간: "
},
"stream": {
"title": "스트림",
"audio": {
"available": "이 스트림에서 오디오를 사용할 수 있습니다",
"unavailable": "이 스트림에서 오디오를 사용할 수 없습니다",
"tips": {
"title": "이 스트림에서 오디오를 사용하려면 카메라에서 오디오를 출력하고 go2rtc에서 설정해야 합니다."
}
},
"debug": {
"picker": "디버그 모드에선 스트림 모드를 선택할 수 없습니다. 디버그 뷰에서는 항상 감지(Detect) 역할로 설정한 스트림을 사용합니다."
},
"twoWayTalk": {
"tips": "양방향 말하기 기능을 사용하려면 기기에서 기능을 지원해야하며 WebRTC를 설정해야합니다.",
"available": "이 기기는 양방향 말하기 기능을 사용할 수 있습니다",
"unavailable": "이 기기는 양방향 말하기 기능을 사용할 수 없습니다"
},
"lowBandwidth": {
"tips": "버퍼링 또는 스트림 오류로 실시간 화면을 저대역폭 모드로 변경되었습니다.",
"resetStream": "스트림 리셋"
},
"playInBackground": {
"label": "백그라운드에서 재생",
"tips": "이 옵션을 활성화하면 플레이어가 숨겨져도 스트리밍이 지속됩니다."
}
},
"cameraSettings": {
"title": "{{camera}} 설정",
"cameraEnabled": "카메라 활성화",
"objectDetection": "대상 감지",
"recording": "녹화",
"snapshots": "스냅샷",
"audioDetection": "오디오 감지",
"transcription": "오디오 자막",
"autotracking": "자동 추적"
},
"history": {
"label": "이전 영상 보기"
},
"effectiveRetainMode": {
"modes": {
"all": "전체",
"motion": "움직임 감지",
"active_objects": "활성 대상"
},
"notAllTips": "{{source}} 녹화 보관 설정이 <code>mode: {{effectiveRetainMode}}</code>로 되어 있어, 이 수동 녹화는 {{effectiveRetainModeName}}이(가) 있는 구간만 저장됩니다."
},
"editLayout": {
"label": "레이아웃 편집",
"group": {
"label": "카메라 그룹 편집"
},
"exitEdit": "편집 종료"
},
"noCameras": {
"title": "설정된 카메라 없음",
"description": "카메라를 연결해 시작하세요.",
"buttonText": "카메라 추가"
},
"snapshot": {
"takeSnapshot": "인스턴트 스냅샷 다운로드",
"noVideoSource": "스냅샷 찍을 비디오 소스가 없습니다.",
"captureFailed": "스냅샷 캡쳐를 하지 못했습니다.",
"downloadStarted": "스냅샷 다운로드가 시작됐습니다."
} }
} }

View File

@ -1,5 +1,12 @@
{ {
"filter": "필터", "filter": "필터",
"export": "내보내기", "export": "내보내기",
"calendar": "달력" "calendar": "날짜",
"filters": "필터",
"toast": {
"error": {
"noValidTimeSelected": "올바른 시간 범위를 선택하세요",
"endTimeMustAfterStartTime": "종료 시간은 시작 시간보다 뒤에 있어야합니다"
}
}
} }

View File

@ -24,11 +24,99 @@
"documentTitle": { "documentTitle": {
"default": "설정 - Frigate", "default": "설정 - Frigate",
"authentication": "인증 설정 - Frigate", "authentication": "인증 설정 - Frigate",
"camera": "카메라 설정 - Frigate" "camera": "카메라 설정 - Frigate",
"enrichments": "고급 설정 - Frigate",
"masksAndZones": "마스크와 구역 편집기 - Frigate",
"motionTuner": "움직임 감지 조정 - Frigate",
"object": "디버그 - Frigate",
"general": "일반 설정 - Frigate",
"frigatePlus": "Frigate+ 설정 - Frigate",
"notifications": "알림 설정 - Frigate",
"cameraManagement": "카메라 관리 - Frigate",
"cameraReview": "카메라 다시보기 설정 - Frigate"
}, },
"users": { "users": {
"table": { "table": {
"actions": "액션" "actions": "액션"
} }
},
"menu": {
"ui": "UI",
"enrichments": "고급",
"cameras": "카메라 설정",
"masksAndZones": "마스크 / 구역",
"motionTuner": "움직임 감지 조정",
"triggers": "트리거",
"debug": "디버그",
"users": "사용자",
"roles": "역할",
"notifications": "알림",
"frigateplus": "Frigate+",
"cameraManagement": "관리",
"cameraReview": "다시보기"
},
"dialog": {
"unsavedChanges": {
"title": "저장되지 않은 변경 사항이 있습니다.",
"desc": "계속하기 전에 변경 사항을 저장하시겠습니까?"
}
},
"cameraSetting": {
"camera": "카메라",
"noCamera": "카메라 없음"
},
"general": {
"title": "일반 세팅",
"liveDashboard": {
"title": "실시간 보기 대시보드",
"automaticLiveView": {
"label": "자동으로 실시간 보기 전환",
"desc": "활동이 감지되면 자동으로 실시간 보기로 전환합니다. 이 옵션을 끄면 대시보드의 카메라 화면은 1분마다 한 번만 갱신됩니다."
},
"playAlertVideos": {
"label": "경보 영상 보기",
"desc": "기본적으로 실시간 보기 대시보드의 최근 경보 영상을 작은 반복 영상으로 재생됩니다. 이 옵션을 끄면 이 기기(또는 브라우저)에서는 정적 이미지로만 표시됩니다."
}
},
"storedLayouts": {
"title": "저장된 레이아웃",
"desc": "카메라 그룹의 화면 배치는 드래그하거나 크기를 조정할 수 있습니다. 변경된 위치는 브라우저의 로컬 저장소에 저장됩니다.",
"clearAll": "레이아웃 지우기"
},
"cameraGroupStreaming": {
"title": "카메라 그룹 스트리밍 설정",
"desc": "각각의 카메라 그룹의 스트리밍 설정은 브라우저의 로컬 저장소에 저장됩니다.",
"clearAll": "스트리밍 설정 모두 지우기"
},
"recordingsViewer": {
"title": "녹화 영상 보기",
"defaultPlaybackRate": {
"label": "기본으로 설정된 다시보기 배속",
"desc": "다시보기 영상 재생할 때 기본 배속을 설정합니다."
}
},
"calendar": {
"title": "캘린더",
"firstWeekday": {
"label": "주 첫째날",
"desc": "다시보기 캘린더에서 주가 시작되는 첫째날을 설정합니다.",
"sunday": "일요일",
"monday": "월요일"
}
},
"toast": {
"success": {
"clearStoredLayout": "{{cameraName}}의 레이아웃을 지웠습니다",
"clearStreamingSettings": "모든 카메라 그룹 스트리밍 설정을 지웠습니다."
},
"error": {
"clearStoredLayoutFailed": "레이아웃 지우기에 실패했습니다:{{errorMessage}}",
"clearStreamingSettingsFailed": "카메라 스트리밍 설정 지우기에 실패했습니다:{{errorMessage}}"
}
}
},
"enrichments": {
"title": "고급 설정",
"unsavedChanges": "변경된 고급 설정을 저장하지 않았습니다"
} }
} }

View File

@ -1,7 +1,186 @@
{ {
"documentTitle": { "documentTitle": {
"cameras": "카메라 통계 - Frigate", "cameras": "카메라 통계 - Frigate",
"storage": "스토리지 통계 - Frigate", "storage": "저장소 통계 - Frigate",
"general": "기본 통계 - Frigate" "general": "기본 통계 - Frigate",
"enrichments": "고급 통계 - Frigate",
"logs": {
"frigate": "Frigate 로그 -Frigate",
"go2rtc": "Go2RTC 로그 - Frigate",
"nginx": "Nginx 로그 - Frigate"
}
},
"title": "시스템",
"metrics": "시스템 통계",
"logs": {
"download": {
"label": "다운로드 로그"
},
"copy": {
"label": "클립보드에 복사하기",
"success": "클립보드에 로그가 복사되었습니다",
"error": "클립보드에 로그를 저장할 수 없습니다"
},
"type": {
"label": "타입",
"timestamp": "시간 기록",
"tag": "태그",
"message": "메시지"
},
"tips": "서버에서 로그 스트리밍 중",
"toast": {
"error": {
"fetchingLogsFailed": "로그 가져오기 오류: {{errorMessage}}",
"whileStreamingLogs": "스크리밍 로그 중 오류: {{errorMessage}}"
}
}
},
"general": {
"title": "기본",
"detector": {
"title": "감지기",
"inferenceSpeed": "감지 추론 속도",
"temperature": "감지기 온도",
"cpuUsage": "감지기 CPU 사용률",
"memoryUsage": "감지기 메모리 사용률",
"cpuUsageInformation": "감지 모델로 데이터를 입력/출력하기 위한 전처리 과정에서 사용되는 CPU 사용량입니다. GPU나 가속기를 사용하는 경우에도 추론 자체의 사용량은 포함되지 않습니다."
},
"hardwareInfo": {
"title": "하드웨어 정보",
"gpuUsage": "GPU 사용률",
"gpuMemory": "GPU 메모리",
"gpuEncoder": "GPU 인코더",
"gpuDecoder": "GPU 디코더",
"gpuInfo": {
"vainfoOutput": {
"title": "Vainfo 출력",
"processOutput": "프로세스 출력:",
"processError": "프로세스 오류:",
"returnCode": "리턴 코드:{{code}}"
},
"nvidiaSMIOutput": {
"title": "Nvidia SMI 출력",
"name": "이름:{{name}}",
"driver": "드라이버:{{driver}}",
"cudaComputerCapability": "CUDA Compute Capability:{{cuda_compute}}",
"vbios": "VBios Info: {{vbios}}"
},
"copyInfo": {
"label": "GPU 정보 복사"
},
"toast": {
"success": "GPU 정보가 클립보드에 복사되었습니다"
},
"closeInfo": {
"label": "GPU 정보 닫기"
}
},
"npuUsage": "NPU 사용률",
"npuMemory": "NPU 메모리"
},
"otherProcesses": {
"title": "다른 프로세스들",
"processCpuUsage": "사용중인 CPU 사용률",
"processMemoryUsage": "사용중인 메모리 사용률"
}
},
"storage": {
"title": "스토리지",
"overview": "전체 현황",
"recordings": {
"title": "녹화",
"tips": "이 값은 Frigate 데이터베이스의 녹화 영상이 사용 중인 전체 저장 공간입니다. Frigate는 디스크 내 다른 파일들의 저장 공간은 추적하지 않습니다.",
"earliestRecording": "가장 오래된 녹화 영상:"
},
"cameraStorage": {
"title": "카메라 저장소",
"camera": "카메라",
"unusedStorageInformation": "미사용 저장소 정보",
"storageUsed": "용량",
"percentageOfTotalUsed": "전체 대비 비율",
"bandwidth": "대역폭",
"unused": {
"title": "미사용",
"tips": "드라이브에 Frigate 녹화 영상 외에 다른 파일이 저장되어 있는 경우, 이 값은 Frigate에서 실제 사용 가능한 여유 공간을 정확히 나타내지 않을 수 있습니다. Frigate는 녹화 영상 외의 저장 공간 사용량을 추적하지 않습니다."
}
},
"shm": {
"title": "SHM (공유 메모리) 할당량",
"warning": "현재 SHM 사이즈가 {{total}}MB로 너무 적습니다. 최소 {{min_shm}}MB 이상 올려주세요."
}
},
"cameras": {
"title": "카메라",
"overview": "전체 현황",
"info": {
"aspectRatio": "종횡비",
"fetching": "카메라 데이터 수집 중",
"stream": "스트림 {{idx}}",
"streamDataFromFFPROBE": "스트림 데이터는 <code>ffprobe</code>에서 받습니다.",
"video": "비디오:",
"codec": "코덱:",
"resolution": "해상도:",
"fps": "FPS:",
"unknown": "알 수 없음",
"audio": "오디오:",
"error": "오류:{{error}}",
"cameraProbeInfo": "{{camera}} 카메라 장치 정보",
"tips": {
"title": "카메라 장치 정보"
}
},
"framesAndDetections": "프레임 / 감지 (Detections)",
"label": {
"camera": "카메라",
"detect": "감지",
"skipped": "건너뜀",
"ffmpeg": "FFmpeg",
"capture": "캡쳐",
"overallFramesPerSecond": "전체 초당 프레임",
"overallDetectionsPerSecond": "전체 초당 감지",
"overallSkippedDetectionsPerSecond": "전체 초당 건너뛴 감지",
"cameraFfmpeg": "{{camName}} FFmpeg",
"cameraCapture": "{{camName}} 캡쳐",
"cameraDetect": "{{camName}} 감지",
"cameraFramesPerSecond": "{{camName}} 초당 프레임",
"cameraDetectionsPerSecond": "{{camName}} 초당 감지",
"cameraSkippedDetectionsPerSecond": "{{camName}} 초당 건너뛴 감지"
},
"toast": {
"success": {
"copyToClipboard": "데이터 정보가 클립보드에 복사되었습니다."
},
"error": {
"unableToProbeCamera": "카메라 정보 알 수 없음: {{errorMessage}}"
}
}
},
"lastRefreshed": "마지막 새로고침: ",
"stats": {
"ffmpegHighCpuUsage": "{{camera}} FFmpeg CPU 사용량이 높습니다 ({{ffmpegAvg}}%)",
"detectHighCpuUsage": "{{camera}} 감지 CPU 사용량이 높습니다 ({{detectAvg}}%)",
"healthy": "시스템 정상",
"reindexingEmbeddings": "Reindexing embeddings ({{processed}}% complete)",
"cameraIsOffline": "{{camera}} 오프라인입니다",
"detectIsSlow": "{{detect}} (이/가) 느립니다 ({{speed}} ms)",
"detectIsVerySlow": "{{detect}} (이/가) 매우 느립니다 ({{speed}} ms)",
"shmTooLow": "/dev/shm 할당량을 ({{total}} MB) 최소 {{min}} MB 이상 증가시켜야합니다."
},
"enrichments": {
"title": "추가 분석 정보",
"infPerSecond": "초당 추론 속도",
"embeddings": {
"image_embedding": "이미지 임베딩",
"text_embedding": "텍스트 임베딩",
"face_recognition": "얼굴 인식",
"plate_recognition": "번호판 인식",
"image_embedding_speed": "이미지 임베딩 속도",
"face_embedding_speed": "얼굴 임베딩 속도",
"face_recognition_speed": "얼굴 인식 속도",
"plate_recognition_speed": "번호판 인식 속도",
"text_embedding_speed": "텍스트 임베딩 속도",
"yolov9_plate_detection_speed": "YOLOv9 플레이트 감지 속도",
"yolov9_plate_detection": "YOLOv9 플레이트 감지"
}
} }
} }

View File

@ -88,6 +88,14 @@
"length": { "length": {
"feet": "pėdos", "feet": "pėdos",
"meters": "metrai" "meters": "metrai"
},
"data": {
"kbps": "kB/s",
"mbps": "MB/s",
"gbps": "GB/s",
"kbph": "kB/val",
"mbph": "MB/val",
"gbph": "GB/val"
} }
}, },
"label": { "label": {
@ -270,5 +278,8 @@
"desc": "Puslapis nerastas" "desc": "Puslapis nerastas"
}, },
"selectItem": "Pasirinkti {{item}}", "selectItem": "Pasirinkti {{item}}",
"readTheDocumentation": "Skaityti dokumentaciją" "readTheDocumentation": "Skaityti dokumentaciją",
"information": {
"pixels": "{{area}}px"
}
} }

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