diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json
index ffdfe6d1a..8fa2451a4 100644
--- a/web/public/locales/en/views/settings.json
+++ b/web/public/locales/en/views/settings.json
@@ -150,6 +150,10 @@
"title": "Streams",
"desc": "Disabling a camera completely stops Frigate's processing of this camera's streams. Detection, recording, and debugging will be unavailable.
Note: This does not disable go2rtc restreams."
},
+ "genai": {
+ "title": "Generative AI",
+ "desc": "Temporarily enable/disable Generative AI for this camera. When disabled, AI generated descriptions will not be requested for tracked objects on this camera."
+ },
"review": {
"title": "Review",
"desc": "Enable/disable alerts and detections for this camera. When disabled, no new review items will be generated.",
diff --git a/web/src/api/ws.tsx b/web/src/api/ws.tsx
index cc3ea05bf..af25e6a51 100644
--- a/web/src/api/ws.tsx
+++ b/web/src/api/ws.tsx
@@ -68,6 +68,7 @@ function useValue(): useValueReturn {
autotracking,
alerts,
detections,
+ genai,
} = state["config"];
cameraStates[`${name}/recordings/state`] = record ? "ON" : "OFF";
cameraStates[`${name}/enabled/state`] = enabled ? "ON" : "OFF";
@@ -89,6 +90,7 @@ function useValue(): useValueReturn {
cameraStates[`${name}/review_detections/state`] = detections
? "ON"
: "OFF";
+ cameraStates[`${name}/genai/state`] = genai ? "ON" : "OFF";
});
setWsState((prevState) => ({
@@ -276,6 +278,17 @@ export function useDetectionsState(camera: string): {
return { payload: payload as ToggleableSetting, send };
}
+export function useGenAIState(camera: string): {
+ payload: ToggleableSetting;
+ send: (payload: ToggleableSetting, retain?: boolean) => void;
+} {
+ const {
+ value: { payload },
+ send,
+ } = useWs(`${camera}/genai/state`, `${camera}/genai/set`);
+ return { payload: payload as ToggleableSetting, send };
+}
+
export function usePtzCommand(camera: string): {
payload: string;
send: (payload: string, retain?: boolean) => void;
diff --git a/web/src/types/ws.ts b/web/src/types/ws.ts
index 7fad6e953..9ecb9cc6f 100644
--- a/web/src/types/ws.ts
+++ b/web/src/types/ws.ts
@@ -64,6 +64,7 @@ export interface FrigateCameraState {
autotracking: boolean;
alerts: boolean;
detections: boolean;
+ genai: boolean;
};
motion: boolean;
objects: ObjectType[];
diff --git a/web/src/views/settings/CameraSettingsView.tsx b/web/src/views/settings/CameraSettingsView.tsx
index db2490f53..ea0e2854f 100644
--- a/web/src/views/settings/CameraSettingsView.tsx
+++ b/web/src/views/settings/CameraSettingsView.tsx
@@ -29,7 +29,12 @@ import { cn } from "@/lib/utils";
import { Trans, useTranslation } from "react-i18next";
import { Switch } from "@/components/ui/switch";
import { Label } from "@/components/ui/label";
-import { useAlertsState, useDetectionsState, useEnabledState } from "@/api/ws";
+import {
+ useAlertsState,
+ useDetectionsState,
+ useEnabledState,
+ useGenAIState,
+} from "@/api/ws";
import CameraEditForm from "@/components/settings/CameraEditForm";
import { LuPlus } from "react-icons/lu";
import {
@@ -142,6 +147,9 @@ export default function CameraSettingsView({
const { payload: detectionsState, send: sendDetections } =
useDetectionsState(selectedCamera);
+ const { payload: genAIState, send: sendGenAI } =
+ useGenAIState(selectedCamera);
+
const handleCheckedChange = useCallback(
(isChecked: boolean) => {
if (!isChecked) {
@@ -402,6 +410,36 @@ export default function CameraSettingsView({
+ {config?.genai?.enabled && (
+ <>
+