* Ensure config editor recalculates layout on error

* ensure empty lists are returned when lpr recognition model fails

* Add docs section for session_length

* clarify

Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>

* clarify

Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>

* Catch missing file

* Improve graph axis colors

* Ensure playback rate controls are portaled to the video container in history view

On larger tablets in landscape view, the playback rate dropdown disappeared underneath the bottom bar. This small change ensures we use the correct container on the DropdownMenuContent so that the div is portaled correctly. The VideoControls are also used in motion review which does not pass in a container ref, so we can just fall back to the existing controlsContainer ref when it's undefined.

---------

Co-authored-by: Nicolas Mowen <nickmowen213@gmail.com>
This commit is contained in:
Josh Hawkins 2025-06-04 20:48:26 -05:00 committed by GitHub
parent dba9206898
commit ed43df9c13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 63 additions and 13 deletions

View File

@ -52,6 +52,21 @@ auth:
- 172.18.0.0/16 # <---- this is the subnet for the internal Docker Compose network
```
## Session Length
The default session length for user authentication in Frigate is 24 hours. This setting determines how long a user's authenticated session remains active before a token refresh is required — otherwise, the user will need to log in again.
While the default provides a balance of security and convenience, you can customize this duration to suit your specific security requirements and user experience preferences. The session length is configured in seconds.
The default value of `86400` will expire the authentication session after 24 hours. Some other examples:
- `0`: Setting the session length to 0 will require a user to log in every time they access the application or after a very short, immediate timeout.
- `604800`: Setting the session length to 604800 will require a user to log in if the token is not refreshed for 7 days.
```yaml
auth:
session_length: 86400
```
## JWT Token Secret
The JWT token secret needs to be kept secure. Anyone with this secret can generate valid JWT tokens to authenticate with Frigate. This should be a cryptographically random string of at least 64 characters.

View File

@ -167,6 +167,8 @@ class LicensePlateProcessingMixin:
outputs = self.model_runner.recognition_model(norm_images)
except Exception as e:
logger.warning(f"Error running LPR recognition model: {e}")
return [], []
return self.ctc_decoder(outputs)
def _process_license_plate(

View File

@ -6,6 +6,7 @@ import json
import logging
import os
import shutil
from pathlib import Path
from typing import Any, Optional
import cv2
@ -538,4 +539,4 @@ class FaceRealTimeProcessor(RealTimeProcessorApi):
# delete oldest face image if maximum is reached
if len(files) > self.config.face_recognition.save_attempts:
os.unlink(os.path.join(folder, files[-1]))
Path(os.path.join(folder, files[-1])).unlink(missing_ok=True)

View File

@ -106,6 +106,9 @@ export function CameraLineGraph({
labels: {
rotate: 0,
formatter: formatTime,
style: {
colors: "#6B6B6B",
},
},
axisBorder: {
show: false,
@ -118,6 +121,9 @@ export function CameraLineGraph({
show: true,
labels: {
formatter: (val: number) => Math.ceil(val).toString(),
style: {
colors: "#6B6B6B",
},
},
min: 0,
},
@ -138,7 +144,7 @@ export function CameraLineGraph({
className="size-2"
style={{ color: GRAPH_COLORS[labelIdx] }}
/>
<div className="text-xs text-muted-foreground">
<div className="text-xs text-secondary-foreground">
{t("cameras.label." + label)}
</div>
<div className="text-xs text-primary">
@ -243,6 +249,9 @@ export function EventsPerSecondsLineGraph({
labels: {
rotate: 0,
formatter: formatTime,
style: {
colors: "#6B6B6B",
},
},
axisBorder: {
show: false,
@ -255,6 +264,9 @@ export function EventsPerSecondsLineGraph({
show: true,
labels: {
formatter: (val: number) => Math.ceil(val).toString(),
style: {
colors: "#6B6B6B",
},
},
min: 0,
},
@ -268,7 +280,7 @@ export function EventsPerSecondsLineGraph({
return (
<div className="flex w-full flex-col">
<div className="flex items-center gap-1">
<div className="text-xs text-muted-foreground">{name}</div>
<div className="text-xs text-secondary-foreground">{name}</div>
<div className="text-xs text-primary">
{lastValue}
{unit}

View File

@ -138,6 +138,9 @@ export function ThresholdBarGraph({
labels: {
rotate: 0,
formatter: formatTime,
style: {
colors: "#6B6B6B",
},
},
axisBorder: {
show: false,
@ -150,6 +153,9 @@ export function ThresholdBarGraph({
show: true,
labels: {
formatter: (val: number) => Math.ceil(val).toString(),
style: {
colors: "#6B6B6B",
},
},
min: 0,
max: yMax,
@ -180,7 +186,7 @@ export function ThresholdBarGraph({
return (
<div className="flex w-full flex-col">
<div className="flex items-center gap-1">
<div className="text-xs text-muted-foreground">{name}</div>
<div className="text-xs text-secondary-foreground">{name}</div>
<div className="text-xs text-primary">
{lastValue}
{unit}

View File

@ -250,7 +250,9 @@ export default function VideoControls({
>
<DropdownMenuTrigger>{`${playbackRate}x`}</DropdownMenuTrigger>
<DropdownMenuContent
portalProps={{ container: controlsContainerRef.current }}
portalProps={{
container: containerRef?.current ?? controlsContainerRef.current,
}}
>
<DropdownMenuRadioGroup
onValueChange={(rate) => onSetPlaybackRate(parseFloat(rate))}

View File

@ -209,13 +209,24 @@ function ConfigEditor() {
};
}, [hasChanges, t]);
useEffect(() => {
if (editorRef.current) {
// Small delay to ensure DOM has updated
const timeoutId = setTimeout(() => {
editorRef.current?.layout();
}, 0);
return () => clearTimeout(timeoutId);
}
}, [error]);
if (!config) {
return <ActivityIndicator />;
}
return (
<div className="absolute bottom-2 left-0 right-0 top-2 md:left-2">
<div className="relative h-full overflow-hidden">
<div className="relative flex h-full flex-col overflow-hidden">
<div className="mr-1 flex items-center justify-between">
<Heading as="h2" className="mb-0 ml-1 md:ml-0">
{t("configEditor")}
@ -254,13 +265,14 @@ function ConfigEditor() {
</div>
</div>
{error && (
<div className="mt-2 max-h-[30%] overflow-auto whitespace-pre-wrap border-2 border-muted bg-background_alt p-4 text-sm text-danger md:max-h-[40%]">
{error}
</div>
)}
<div ref={configRef} className="mt-2 h-[calc(100%-2.75rem)]" />
<div className="flex flex-1 flex-col overflow-hidden">
{error && (
<div className="mt-2 max-h-[30%] min-h-[2.5rem] overflow-auto whitespace-pre-wrap border-2 border-muted bg-background_alt p-4 text-sm text-danger md:max-h-[40%]">
{error}
</div>
)}
<div ref={configRef} className="flex-1 overflow-hidden" />
</div>
</div>
<Toaster closeButton={true} />
<RestartDialog