diff --git a/docs/docs/configuration/object_detectors.md b/docs/docs/configuration/object_detectors.md
index 4a197da451..4bd99ed8f1 100644
--- a/docs/docs/configuration/object_detectors.md
+++ b/docs/docs/configuration/object_detectors.md
@@ -73,6 +73,22 @@ This does not affect using hardware for accelerating other tasks such as [semant
:::
+### Choosing a model size
+
+Along with picking a detector for your hardware, you will choose a model's **input resolution** (such as `320x320` or `640x640`) and, for model families like YOLOv9, a **variant size** (`tiny`, `small`, etc.). Both affect the balance between accuracy and the inference time your hardware can sustain.
+
+**Resolution (320x320 vs 640x640):** Frigate is optimized for `320x320` models, and `320x320` is the best choice for the vast majority of setups. Frigate is specifically designed to compensate for the smaller model by cropping a region of motion from the full frame and zooming into it before running detection, so a `320x320` model is actually _better_ at small and distant objects — not worse. A `640x640` model is slower and uses more resources, and its main benefit is fitting more objects into a single inference when many objects are spread across a large area. Recent versions of Frigate have improved support for `640x640` models, but `320x320` remains the recommended starting point for nearly all setups.
+
+**Variant size (tiny/small/medium):** Larger variants are gradually more accurate but slower. Whether the difference is noticeable depends on your specific cameras and scenes. A good rule of thumb is to use the largest model your hardware can run without skipping detections, which you can monitor on the page in the UI — better accuracy only helps if your detector keeps up with the detection load across all cameras.
+
+**Acceptable inference time depends on your hardware.** Inference time alone does not tell the whole story, because different hardware has different capacity. A GPU can run multiple instances of the same model concurrently, so an inference time around 30ms can still keep up with several cameras. A Google Coral runs only a single instance of the model, so it needs a much lower inference time (around 10ms) to keep up.
+
+:::tip
+
+The best detection accuracy comes from a model trained on images that look like what Frigate actually sees — security camera footage cropped to regions of interest. You can train or fine-tune your own model on images like this and run it as a custom model (see the per-detector sections below), but [Frigate+](/plus) makes this much easier by handling the training for you on images submitted from your own cameras. For YOLOv9, the `s` (small) variant at `320x320` resolution is a good place to start.
+
+:::
+
# Officially Supported Detectors
Frigate provides a number of builtin detector types. By default, Frigate will use a single CPU detector. Other detectors may require additional configuration as described below. When using multiple detectors they will run in dedicated processes, but pull from a common queue of detection requests from across all cameras.
diff --git a/docs/docs/usage/history.md b/docs/docs/usage/history.md
index 809d818ab2..a978a3c45a 100644
--- a/docs/docs/usage/history.md
+++ b/docs/docs/usage/history.md
@@ -29,7 +29,7 @@ If you see **"No recordings found for this time"**, the most common causes are:
A toggle (a drawer on mobile) switches the side panel between three modes:
-- **Timeline** — a scrubbable vertical timeline of the selected camera, annotated with a motion line, review-item markers, and gaps where no recording exists.
+- **Timeline** — a scrubbable vertical timeline of the selected camera. Horizontal lines down the center represent motion, with longer lines indicating more motion at that moment. Review items are marked as shaded areas (**red** for alerts, **orange** for detections), and sections with no colored background are times when no recording exists.
- **Events** — a scrollable list of the camera's review items for the time range; clicking one seeks the player to it.
- **Detail** — the [tracking details inspector](#the-detail-view) for the objects in view.
diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json
index e4bd7ae517..37cf676c8c 100644
--- a/web/public/locales/en/views/settings.json
+++ b/web/public/locales/en/views/settings.json
@@ -1924,6 +1924,10 @@
"resolutionHigh": "This detect resolution is higher than recommended and may cause increased resource usage without improving detection accuracy. A detect resolution at or below 1080p is recommended for most cameras.",
"globalResolutionMultipleCameras": "A global detect resolution is set while multiple cameras are configured. Unless all cameras share the same resolution and aspect ratio, the detect width and height should be defined per camera to match each camera's native aspect ratio."
},
+ "model": {
+ "optimizedFor320": "Frigate is optimized for a 320x320 model, which is the best choice for most setups. A 640x640 model is slower and only helps in specific scenarios.",
+ "inputDimensionsNotDetectResolution": "Model input width and height are the input dimensions of the object detection model, not your camera's detect resolution. They should match the dimensions of the model you're using — typically a square size like 320x320 or 640x640."
+ },
"ffmpeg": {
"hwaccelManualNotRecommended": "Manual hardware acceleration arguments are not recommended. Unless a specific requirement exists, select the preset that matches your hardware."
},
diff --git a/web/src/components/config-form/ConfigFieldMessage.tsx b/web/src/components/config-form/ConfigFieldMessage.tsx
index 545d50ba7c..78921c1605 100644
--- a/web/src/components/config-form/ConfigFieldMessage.tsx
+++ b/web/src/components/config-form/ConfigFieldMessage.tsx
@@ -1,6 +1,13 @@
import { useTranslation } from "react-i18next";
+import { Link } from "react-router-dom";
import { Alert, AlertDescription } from "@/components/ui/alert";
-import { LuInfo, LuTriangleAlert, LuCircleAlert } from "react-icons/lu";
+import {
+ LuInfo,
+ LuTriangleAlert,
+ LuCircleAlert,
+ LuExternalLink,
+} from "react-icons/lu";
+import { useDocDomain } from "@/hooks/use-doc-domain";
import type { MessageSeverity } from "./section-configs/types";
const severityVariantMap: Record<
@@ -28,13 +35,18 @@ function SeverityIcon({ severity }: { severity: string }) {
type ConfigFieldMessageProps = {
messageKey: string;
severity: string;
+ values?: Record;
+ docLink?: string;
};
export function ConfigFieldMessage({
messageKey,
severity,
+ values,
+ docLink,
}: ConfigFieldMessageProps) {
- const { t } = useTranslation("views/settings");
+ const { t } = useTranslation(["views/settings", "common"]);
+ const { getLocaleDocUrl } = useDocDomain();
return (
- {t(messageKey)}
+
+