feat: Add support for Frigate reviews / detections [initial PR] (#2315)

- Add support for Frigate reviews / detections.
 - Add support for GenAI metadata.
- Significant internal refactor to more flexible "UnifiedQuery" to allow
mixing cameras with simple metadata and review metadata (e.g. a timeline
view of a Frigate camera with reviews, and a Reolink camera with simple
metadata).
 - Add support for folder media as camera media.

There are a few more PRs to commit prior to this going live, but
commiting this for now due to the scale of the change.

BREAKING CHANGE: `media_type` and `events_type` are retired under
`live`, `viewer` and `timeline` configuration sections, instead media
type is associated (once) with the camera under `media`.
This commit is contained in:
Dermot Duffy
2026-01-19 13:32:50 -08:00
committed by GitHub
parent 6eb0a87ca8
commit fc32727860
215 changed files with 14491 additions and 6160 deletions
+39 -1
View File
@@ -3,6 +3,8 @@ import { capabilityKeys } from '../../types';
import { mediaLayoutConfigSchema } from './camera/media-layout';
import { ptzCameraConfigDefaults, ptzCameraConfigSchema } from './camera/ptz';
import { aspectRatioSchema } from './common/aspect-ratio';
import { eventsMediaTypeSchema } from './common/events-media';
import { severitySchema } from './common/severity';
import { imageBaseConfigSchema, imageConfigDefault } from './common/image';
const CAMERA_TRIGGER_EVENT_TYPES = [
@@ -124,8 +126,12 @@ export const cameraConfigDefault = {
triggers: {
motion: false,
occupancy: false,
events: [...CAMERA_TRIGGER_EVENT_TYPES],
events: [],
entities: [],
reviews: {
severities: ['high' as const],
description: true,
},
},
proxy: {
dynamic: true,
@@ -173,6 +179,26 @@ const cameraDimensionsSchema = z.object({
});
export type CameraDimensionsConfig = z.infer<typeof cameraDimensionsSchema>;
// Camera media configuration for default media type in live/timeline views.
const CAMERA_MEDIA_TYPES = [
'auto',
'reviews',
'events',
'recordings',
'folder',
] as const;
export type CameraMediaType = (typeof CAMERA_MEDIA_TYPES)[number];
const cameraMediaConfigDefault = {
type: 'auto' as CameraMediaType,
};
const cameraMediaConfigSchema = z.object({
type: z.enum(CAMERA_MEDIA_TYPES).default(cameraMediaConfigDefault.type),
events_type: eventsMediaTypeSchema.optional(),
folders: z.array(z.string()).optional(),
});
export const cameraConfigSchema = z
.object({
camera_entity: z.string().optional(),
@@ -209,6 +235,16 @@ export const cameraConfigSchema = z
.enum(CAMERA_TRIGGER_EVENT_TYPES)
.array()
.default(cameraConfigDefault.triggers.events),
reviews: z
.object({
severities: severitySchema
.array()
.default([...cameraConfigDefault.triggers.reviews.severities]),
description: z
.boolean()
.default(cameraConfigDefault.triggers.reviews.description),
})
.default(cameraConfigDefault.triggers.reviews),
})
.default(cameraConfigDefault.triggers),
@@ -274,6 +310,8 @@ export const cameraConfigSchema = z
dimensions: cameraDimensionsSchema.optional(),
media: cameraMediaConfigSchema.optional(),
proxy: proxyConfigSchema.default(cameraConfigDefault.proxy),
// See: https://github.com/dermotduffy/advanced-camera-card/issues/1650