mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-08-04 13:47:37 +02:00
Fixes (#18795)
* Catch error when regex is invalid * Fix i18n label * Mobile camera drawer i18n fixes * additional frame cache debug logs * Add Romanian * Fix exports thumbnail path * Improve clip buffer and remove outdated comments --------- Co-authored-by: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com>
This commit is contained in:
parent
4ff81d5877
commit
8a9ebe9292
@ -598,7 +598,7 @@ def recording_clip(
|
|||||||
if clip.start_time < start_ts:
|
if clip.start_time < start_ts:
|
||||||
file.write(f"inpoint {int(start_ts - clip.start_time)}\n")
|
file.write(f"inpoint {int(start_ts - clip.start_time)}\n")
|
||||||
|
|
||||||
# if this is the ending clip and end trim is enabled, add an outpoint
|
# if this is the ending clip, add an outpoint
|
||||||
if clip.end_time > end_ts:
|
if clip.end_time > end_ts:
|
||||||
file.write(f"outpoint {int(end_ts - clip.start_time)}\n")
|
file.write(f"outpoint {int(end_ts - clip.start_time)}\n")
|
||||||
|
|
||||||
|
@ -350,6 +350,7 @@ class CameraState:
|
|||||||
removed_obj = tracked_objects[id]
|
removed_obj = tracked_objects[id]
|
||||||
if "end_time" not in removed_obj.obj_data:
|
if "end_time" not in removed_obj.obj_data:
|
||||||
removed_obj.obj_data["end_time"] = frame_time
|
removed_obj.obj_data["end_time"] = frame_time
|
||||||
|
logger.debug(f"{self.name}: end callback for object {id}")
|
||||||
for c in self.callbacks["end"]:
|
for c in self.callbacks["end"]:
|
||||||
c(self.name, removed_obj, frame_name)
|
c(self.name, removed_obj, frame_name)
|
||||||
|
|
||||||
@ -441,6 +442,17 @@ class CameraState:
|
|||||||
for t in self.frame_cache.keys()
|
for t in self.frame_cache.keys()
|
||||||
if t not in current_thumb_frames and t not in current_best_frames
|
if t not in current_thumb_frames and t not in current_best_frames
|
||||||
]
|
]
|
||||||
|
if len(thumb_frames_to_delete) > 0:
|
||||||
|
logger.debug(f"{self.name}: Current frame cache contents:")
|
||||||
|
for k, v in self.frame_cache.items():
|
||||||
|
logger.debug(f" frame time: {k}, object id: {v['object_id']}")
|
||||||
|
for obj_id, obj in tracked_objects.items():
|
||||||
|
thumb_time = (
|
||||||
|
obj.thumbnail_data["frame_time"] if obj.thumbnail_data else None
|
||||||
|
)
|
||||||
|
logger.debug(
|
||||||
|
f"{self.name}: Tracked object {obj_id} thumbnail frame_time: {thumb_time}"
|
||||||
|
)
|
||||||
for t in thumb_frames_to_delete:
|
for t in thumb_frames_to_delete:
|
||||||
object_id = self.frame_cache[t].get("object_id", "unknown")
|
object_id = self.frame_cache[t].get("object_id", "unknown")
|
||||||
logger.debug(f"{self.name}: Deleting {t} from frame cache for {object_id}")
|
logger.debug(f"{self.name}: Deleting {t} from frame cache for {object_id}")
|
||||||
|
@ -1500,18 +1500,24 @@ class LicensePlateProcessingMixin:
|
|||||||
|
|
||||||
# Determine subLabel based on known plates, use regex matching
|
# Determine subLabel based on known plates, use regex matching
|
||||||
# Default to the detected plate, use label name if there's a match
|
# Default to the detected plate, use label name if there's a match
|
||||||
sub_label = next(
|
try:
|
||||||
(
|
sub_label = next(
|
||||||
label
|
(
|
||||||
for label, plates in self.lpr_config.known_plates.items()
|
label
|
||||||
if any(
|
for label, plates in self.lpr_config.known_plates.items()
|
||||||
re.match(f"^{plate}$", top_plate)
|
if any(
|
||||||
or distance(plate, top_plate) <= self.lpr_config.match_distance
|
re.match(f"^{plate}$", top_plate)
|
||||||
for plate in plates
|
or distance(plate, top_plate) <= self.lpr_config.match_distance
|
||||||
)
|
for plate in plates
|
||||||
),
|
)
|
||||||
None,
|
),
|
||||||
)
|
None,
|
||||||
|
)
|
||||||
|
except re.error:
|
||||||
|
logger.error(
|
||||||
|
f"{camera}: Invalid regex in known plates configuration: {self.lpr_config.known_plates}"
|
||||||
|
)
|
||||||
|
sub_label = None
|
||||||
|
|
||||||
# If it's a known plate, publish to sub_label
|
# If it's a known plate, publish to sub_label
|
||||||
if sub_label is not None:
|
if sub_label is not None:
|
||||||
|
@ -126,7 +126,7 @@ class RecordingExporter(threading.Thread):
|
|||||||
minutes = int(diff / 60)
|
minutes = int(diff / 60)
|
||||||
seconds = int(diff % 60)
|
seconds = int(diff % 60)
|
||||||
ffmpeg_cmd = [
|
ffmpeg_cmd = [
|
||||||
"7.0",
|
"/usr/lib/ffmpeg/7.0/bin/ffmpeg", # hardcode path for exports thumbnail due to missing libwebp support
|
||||||
"-hide_banner",
|
"-hide_banner",
|
||||||
"-loglevel",
|
"-loglevel",
|
||||||
"warning",
|
"warning",
|
||||||
|
@ -48,7 +48,7 @@ import {
|
|||||||
TooltipContent,
|
TooltipContent,
|
||||||
TooltipTrigger,
|
TooltipTrigger,
|
||||||
} from "@/components/ui/tooltip";
|
} from "@/components/ui/tooltip";
|
||||||
import { ReviewSegment } from "@/types/review";
|
import { REVIEW_PADDING, ReviewSegment } from "@/types/review";
|
||||||
import { useNavigate } from "react-router-dom";
|
import { useNavigate } from "react-router-dom";
|
||||||
import Chip from "@/components/indicators/Chip";
|
import Chip from "@/components/indicators/Chip";
|
||||||
import { capitalizeAll } from "@/utils/stringUtil";
|
import { capitalizeAll } from "@/utils/stringUtil";
|
||||||
@ -1229,11 +1229,14 @@ export function VideoTab({ search }: VideoTabProps) {
|
|||||||
const { data: reviewItem } = useSWR<ReviewSegment>([
|
const { data: reviewItem } = useSWR<ReviewSegment>([
|
||||||
`review/event/${search.id}`,
|
`review/event/${search.id}`,
|
||||||
]);
|
]);
|
||||||
const endTime = useMemo(() => search.end_time ?? Date.now() / 1000, [search]);
|
|
||||||
|
|
||||||
// subtract 2 seconds from start_time to account for keyframes and any differences in the record/detect streams
|
const clipTimeRange = useMemo(() => {
|
||||||
// to help the start of the event from not being completely cut off
|
const startTime = search.start_time - REVIEW_PADDING;
|
||||||
const source = `${baseUrl}vod/${search.camera}/start/${search.start_time - 2}/end/${endTime}/index.m3u8`;
|
const endTime = (search.end_time ?? Date.now() / 1000) + REVIEW_PADDING;
|
||||||
|
return `start/${startTime}/end/${endTime}`;
|
||||||
|
}, [search]);
|
||||||
|
|
||||||
|
const source = `${baseUrl}vod/${search.camera}/${clipTimeRange}/index.m3u8`;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@ -1272,7 +1275,7 @@ export function VideoTab({ search }: VideoTabProps) {
|
|||||||
<TooltipTrigger asChild>
|
<TooltipTrigger asChild>
|
||||||
<a
|
<a
|
||||||
download
|
download
|
||||||
href={`${baseUrl}api/${search.camera}/start/${search.start_time}/end/${endTime}/clip.mp4?trim=end`}
|
href={`${baseUrl}api/${search.camera}/${clipTimeRange}/clip.mp4`}
|
||||||
>
|
>
|
||||||
<Chip className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500">
|
<Chip className="cursor-pointer rounded-md bg-gray-500 bg-gradient-to-br from-gray-400 to-gray-500">
|
||||||
<FaDownload className="size-4 text-white" />
|
<FaDownload className="size-4 text-white" />
|
||||||
|
@ -6,6 +6,7 @@ export const supportedLanguageKeys = [
|
|||||||
"de",
|
"de",
|
||||||
"it",
|
"it",
|
||||||
"ca",
|
"ca",
|
||||||
|
"ro",
|
||||||
"nl",
|
"nl",
|
||||||
"nb-NO",
|
"nb-NO",
|
||||||
"zh-CN",
|
"zh-CN",
|
||||||
|
@ -1578,7 +1578,7 @@ function FrigateCameraFeatures({
|
|||||||
<div className="mt-3 flex flex-col gap-5">
|
<div className="mt-3 flex flex-col gap-5">
|
||||||
{!isRestreamed && (
|
{!isRestreamed && (
|
||||||
<div className="flex flex-col gap-2 p-2">
|
<div className="flex flex-col gap-2 p-2">
|
||||||
<Label>{t("streaming.title", { ns: "components/dialog" })}</Label>
|
<Label>{t("stream.title")}</Label>
|
||||||
<div className="flex flex-row items-center gap-1 text-sm text-muted-foreground">
|
<div className="flex flex-row items-center gap-1 text-sm text-muted-foreground">
|
||||||
<LuX className="size-4 text-danger" />
|
<LuX className="size-4 text-danger" />
|
||||||
<div>
|
<div>
|
||||||
@ -1596,7 +1596,7 @@ function FrigateCameraFeatures({
|
|||||||
</div>
|
</div>
|
||||||
</PopoverTrigger>
|
</PopoverTrigger>
|
||||||
<PopoverContent className="w-80 text-xs">
|
<PopoverContent className="w-80 text-xs">
|
||||||
{t("streaming.restreaming.desc", {
|
{t("streaming.restreaming.desc.title", {
|
||||||
ns: "components/dialog",
|
ns: "components/dialog",
|
||||||
})}
|
})}
|
||||||
<div className="mt-2 flex items-center text-primary">
|
<div className="mt-2 flex items-center text-primary">
|
||||||
@ -1606,7 +1606,7 @@ function FrigateCameraFeatures({
|
|||||||
rel="noopener noreferrer"
|
rel="noopener noreferrer"
|
||||||
className="inline"
|
className="inline"
|
||||||
>
|
>
|
||||||
{t("streaming.restreaming.readTheDocumentation", {
|
{t("streaming.restreaming.desc.readTheDocumentation", {
|
||||||
ns: "components/dialog",
|
ns: "components/dialog",
|
||||||
})}
|
})}
|
||||||
<LuExternalLink className="ml-2 inline-flex size-3" />
|
<LuExternalLink className="ml-2 inline-flex size-3" />
|
||||||
|
Loading…
Reference in New Issue
Block a user