From e473117705c0ca310062867bfeda7302c68808de Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 3 Dec 2025 11:11:44 -0700 Subject: [PATCH 01/16] Remove source_type from API --- docs/static/frigate-api.yaml | 1095 +++++++++++------------ frigate/api/defs/request/events_body.py | 1 - frigate/api/event.py | 2 +- 3 files changed, 545 insertions(+), 553 deletions(-) diff --git a/docs/static/frigate-api.yaml b/docs/static/frigate-api.yaml index 123208d3e..1b3e37eb6 100644 --- a/docs/static/frigate-api.yaml +++ b/docs/static/frigate-api.yaml @@ -17,7 +17,7 @@ paths: summary: Auth operationId: auth_auth_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -29,7 +29,7 @@ paths: summary: Profile operationId: profile_profile_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -41,7 +41,7 @@ paths: summary: Logout operationId: logout_logout_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -57,19 +57,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AppPostLoginBody' + $ref: "#/components/schemas/AppPostLoginBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /users: get: tags: @@ -77,7 +77,7 @@ paths: summary: Get Users operationId: get_users_users_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -92,19 +92,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AppPostUsersBody' + $ref: "#/components/schemas/AppPostUsersBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /users/{username}: delete: tags: @@ -119,17 +119,17 @@ paths: type: string title: Username responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /users/{username}/password: put: tags: @@ -148,19 +148,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AppPutPasswordBody' + $ref: "#/components/schemas/AppPutPasswordBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /users/{username}/role: put: tags: @@ -179,19 +179,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AppPutRoleBody' + $ref: "#/components/schemas/AppPutRoleBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /faces: get: tags: @@ -204,12 +204,12 @@ paths: .jpg, and .jpeg. operationId: get_faces_faces_get responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/FacesResponse' + $ref: "#/components/schemas/FacesResponse" /faces/reprocess: post: tags: @@ -228,17 +228,17 @@ paths: type: object title: Body responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /faces/train/{name}/classify: post: tags: @@ -266,18 +266,18 @@ paths: type: object title: Body responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /faces/{name}/create: post: tags: @@ -297,18 +297,18 @@ paths: type: string title: Name responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /faces/{name}/register: post: tags: @@ -336,18 +336,18 @@ paths: $ref: >- #/components/schemas/Body_register_face_faces__name__register_post responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /faces/recognize: post: tags: @@ -363,20 +363,20 @@ paths: content: multipart/form-data: schema: - $ref: '#/components/schemas/Body_recognize_face_faces_recognize_post' + $ref: "#/components/schemas/Body_recognize_face_faces_recognize_post" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/FaceRecognitionResponse' - '422': + $ref: "#/components/schemas/FaceRecognitionResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /faces/{name}/delete: post: tags: @@ -400,20 +400,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/DeleteFaceImagesBody' + $ref: "#/components/schemas/DeleteFaceImagesBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /faces/{old_name}/rename: put: tags: @@ -435,20 +435,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/RenameFaceBody' + $ref: "#/components/schemas/RenameFaceBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /lpr/reprocess: put: tags: @@ -468,17 +468,17 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /reindex: put: tags: @@ -489,12 +489,12 @@ paths: Requires semantic search to be enabled in the configuration. Returns a success message or an error if semantic search is not enabled. operationId: reindex_embeddings_reindex_put responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' + $ref: "#/components/schemas/GenericResponse" /audio/transcribe: put: tags: @@ -510,20 +510,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AudioTranscriptionBody' + $ref: "#/components/schemas/AudioTranscriptionBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /classification/{name}/dataset: get: tags: @@ -541,17 +541,17 @@ paths: type: string title: Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /classification/{name}/train: get: tags: @@ -569,17 +569,17 @@ paths: type: string title: Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" post: tags: - Classification @@ -596,18 +596,18 @@ paths: type: string title: Name responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /classification/{name}/dataset/{category}/delete: post: tags: @@ -639,18 +639,18 @@ paths: type: object title: Body responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /classification/{name}/dataset/categorize: post: tags: @@ -676,18 +676,18 @@ paths: type: object title: Body responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /classification/{name}/train/delete: post: tags: @@ -712,18 +712,18 @@ paths: type: object title: Body responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review: get: tags: @@ -769,7 +769,7 @@ paths: in: query required: false schema: - $ref: '#/components/schemas/SeverityEnum' + $ref: "#/components/schemas/SeverityEnum" - name: before in: query required: false @@ -783,21 +783,21 @@ paths: type: number title: After responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/ReviewSegmentResponse' + $ref: "#/components/schemas/ReviewSegmentResponse" title: Response Review Review Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review_ids: get: tags: @@ -812,21 +812,21 @@ paths: type: string title: Ids responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/ReviewSegmentResponse' + $ref: "#/components/schemas/ReviewSegmentResponse" title: Response Review Ids Review Ids Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review/summary: get: tags: @@ -863,18 +863,18 @@ paths: default: utc title: Timezone responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/ReviewSummaryResponse' - '422': + $ref: "#/components/schemas/ReviewSummaryResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /reviews/viewed: post: tags: @@ -886,20 +886,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ReviewModifyMultipleBody' + $ref: "#/components/schemas/ReviewModifyMultipleBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /reviews/delete: post: tags: @@ -911,20 +911,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ReviewModifyMultipleBody' + $ref: "#/components/schemas/ReviewModifyMultipleBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review/activity/motion: get: tags: @@ -960,21 +960,21 @@ paths: default: 30 title: Scale responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/ReviewActivityMotionResponse' + $ref: "#/components/schemas/ReviewActivityMotionResponse" title: Response Motion Activity Review Activity Motion Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review/event/{event_id}: get: tags: @@ -989,18 +989,18 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/ReviewSegmentResponse' - '422': + $ref: "#/components/schemas/ReviewSegmentResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review/{review_id}: get: tags: @@ -1015,18 +1015,18 @@ paths: type: string title: Review Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/ReviewSegmentResponse' - '422': + $ref: "#/components/schemas/ReviewSegmentResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review/{review_id}/viewed: delete: tags: @@ -1041,18 +1041,18 @@ paths: type: string title: Review Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review/summarize/start/{start_ts}/end/{end_ts}: post: tags: @@ -1075,17 +1075,17 @@ paths: type: number title: End Ts responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /: get: tags: @@ -1093,7 +1093,7 @@ paths: summary: Is Healthy operationId: is_healthy__get responses: - '200': + "200": description: Successful Response content: text/plain: @@ -1106,7 +1106,7 @@ paths: summary: Config Schema operationId: config_schema_config_schema_json_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1118,7 +1118,7 @@ paths: summary: Go2Rtc Streams operationId: go2rtc_streams_go2rtc_streams_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1137,17 +1137,17 @@ paths: type: string title: Camera Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /version: get: tags: @@ -1155,7 +1155,7 @@ paths: summary: Version operationId: version_version_get responses: - '200': + "200": description: Successful Response content: text/plain: @@ -1168,7 +1168,7 @@ paths: summary: Stats operationId: stats_stats_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1187,17 +1187,17 @@ paths: type: string title: Keys responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /metrics: get: tags: @@ -1206,7 +1206,7 @@ paths: description: Expose Prometheus metrics endpoint and update metrics with latest stats operationId: metrics_metrics_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1218,7 +1218,7 @@ paths: summary: Config operationId: config_config_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1230,7 +1230,7 @@ paths: summary: Config Raw operationId: config_raw_config_raw_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1255,17 +1255,17 @@ paths: schema: title: Body responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /config/set: put: tags: @@ -1277,19 +1277,19 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/AppConfigSetBody' + $ref: "#/components/schemas/AppConfigSetBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /ffprobe: get: tags: @@ -1302,20 +1302,20 @@ paths: required: false schema: type: string - default: '' + default: "" title: Paths responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /vainfo: get: tags: @@ -1323,7 +1323,7 @@ paths: summary: Vainfo operationId: vainfo_vainfo_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1335,7 +1335,7 @@ paths: summary: Nvinfo operationId: nvinfo_nvinfo_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1365,7 +1365,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Download - name: stream in: query @@ -1373,7 +1373,7 @@ paths: schema: anyOf: - type: boolean - - type: 'null' + - type: "null" default: false title: Stream - name: start @@ -1382,7 +1382,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 0 title: Start - name: end @@ -1391,20 +1391,20 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: End responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /restart: post: tags: @@ -1412,7 +1412,7 @@ paths: summary: Restart operationId: restart_restart_post responses: - '200': + "200": description: Successful Response content: application/json: @@ -1429,20 +1429,20 @@ paths: required: false schema: type: string - default: '' + default: "" title: Camera responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /sub_labels: get: tags: @@ -1456,20 +1456,20 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Split Joined responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /plus/models: get: tags: @@ -1485,17 +1485,17 @@ paths: default: false title: Filterbycurrentmodeldetector responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /recognized_license_plates: get: tags: @@ -1509,20 +1509,20 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Split Joined responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /timeline: get: tags: @@ -1550,20 +1550,20 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Source Id responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /timeline/hourly: get: tags: @@ -1578,7 +1578,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Cameras - name: labels @@ -1587,7 +1587,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Labels - name: after @@ -1596,7 +1596,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: After - name: before in: query @@ -1604,7 +1604,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Before - name: limit in: query @@ -1612,7 +1612,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 200 title: Limit - name: timezone @@ -1621,21 +1621,21 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: utc title: Timezone responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /preview/{camera_name}/start/{start_ts}/end/{end_ts}: get: tags: @@ -1654,7 +1654,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: start_ts in: path @@ -1669,23 +1669,23 @@ paths: type: number title: End Ts responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/PreviewModel' + $ref: "#/components/schemas/PreviewModel" title: >- Response Preview Ts Preview Camera Name Start Start Ts End End Ts Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /preview/{year_month}/{day}/{hour}/{camera_name}/{tz_name}: get: tags: @@ -1723,7 +1723,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: tz_name in: path @@ -1732,23 +1732,23 @@ paths: type: string title: Tz Name responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/PreviewModel' + $ref: "#/components/schemas/PreviewModel" title: >- Response Preview Hour Preview Year Month Day Hour Camera Name Tz Name Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /preview/{camera_name}/start/{start_ts}/end/{end_ts}/frames: get: tags: @@ -1768,7 +1768,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: start_ts in: path @@ -1783,7 +1783,7 @@ paths: type: number title: End Ts responses: - '200': + "200": description: Successful Response content: application/json: @@ -1794,12 +1794,12 @@ paths: title: >- Response Get Preview Frames From Cache Preview Camera Name Start Start Ts End End Ts Frames Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /notifications/pubkey: get: tags: @@ -1810,7 +1810,7 @@ paths: Returns the public key or an error if notifications are not enabled. operationId: get_vapid_pub_key_notifications_pubkey_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -1831,17 +1831,17 @@ paths: type: object title: Body responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /exports: get: tags: @@ -1852,14 +1852,14 @@ paths: Returns a list of exports ordered by date (most recent first). operationId: get_exports_exports_get responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/ExportModel' + $ref: "#/components/schemas/ExportModel" title: Response Get Exports Exports Get /export/{camera_name}/start/{start_time}/end/{end_time}: post: @@ -1880,7 +1880,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: start_time in: path @@ -1899,20 +1899,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ExportRecordingsBody' + $ref: "#/components/schemas/ExportRecordingsBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/StartExportResponse' - '422': + $ref: "#/components/schemas/StartExportResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /export/{event_id}/rename: patch: tags: @@ -1934,20 +1934,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/ExportRenameBody' + $ref: "#/components/schemas/ExportRenameBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /export/{event_id}: delete: tags: @@ -1962,18 +1962,18 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /exports/{export_id}: get: tags: @@ -1991,18 +1991,18 @@ paths: type: string title: Export Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/ExportModel' - '422': + $ref: "#/components/schemas/ExportModel" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events: get: tags: @@ -2017,7 +2017,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Camera - name: cameras @@ -2026,7 +2026,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Cameras - name: label @@ -2035,7 +2035,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Label - name: labels @@ -2044,7 +2044,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Labels - name: sub_label @@ -2053,7 +2053,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Sub Label - name: sub_labels @@ -2062,7 +2062,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Sub Labels - name: zone @@ -2071,7 +2071,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Zone - name: zones @@ -2080,7 +2080,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Zones - name: limit @@ -2089,7 +2089,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 100 title: Limit - name: after @@ -2098,7 +2098,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: After - name: before in: query @@ -2106,7 +2106,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Before - name: time_range in: query @@ -2114,7 +2114,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: 00:00,24:00 title: Time Range - name: has_clip @@ -2123,7 +2123,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Has Clip - name: has_snapshot in: query @@ -2131,7 +2131,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Has Snapshot - name: in_progress in: query @@ -2139,7 +2139,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: In Progress - name: include_thumbnails in: query @@ -2147,7 +2147,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 1 title: Include Thumbnails - name: favorites @@ -2156,7 +2156,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Favorites - name: min_score in: query @@ -2164,7 +2164,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Min Score - name: max_score in: query @@ -2172,7 +2172,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Max Score - name: min_speed in: query @@ -2180,7 +2180,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Min Speed - name: max_speed in: query @@ -2188,7 +2188,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Max Speed - name: recognized_license_plate in: query @@ -2196,7 +2196,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Recognized License Plate - name: is_submitted @@ -2205,7 +2205,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Is Submitted - name: min_length in: query @@ -2213,7 +2213,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Min Length - name: max_length in: query @@ -2221,7 +2221,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Max Length - name: event_id in: query @@ -2229,7 +2229,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Event Id - name: sort in: query @@ -2237,7 +2237,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Sort - name: timezone in: query @@ -2245,25 +2245,25 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: utc title: Timezone responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/EventResponse' + $ref: "#/components/schemas/EventResponse" title: Response Events Events Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/explore: get: tags: @@ -2282,21 +2282,21 @@ paths: default: 10 title: Limit responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/EventResponse' + $ref: "#/components/schemas/EventResponse" title: Response Events Explore Events Explore Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /event_ids: get: tags: @@ -2314,21 +2314,21 @@ paths: type: string title: Ids responses: - '200': + "200": description: Successful Response content: application/json: schema: type: array items: - $ref: '#/components/schemas/EventResponse' + $ref: "#/components/schemas/EventResponse" title: Response Event Ids Event Ids Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/search: get: tags: @@ -2345,7 +2345,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Query - name: event_id in: query @@ -2353,7 +2353,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Event Id - name: search_type in: query @@ -2361,7 +2361,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: thumbnail title: Search Type - name: include_thumbnails @@ -2370,7 +2370,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 1 title: Include Thumbnails - name: limit @@ -2379,7 +2379,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 50 title: Limit - name: cameras @@ -2388,7 +2388,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Cameras - name: labels @@ -2397,7 +2397,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Labels - name: zones @@ -2406,7 +2406,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Zones - name: after @@ -2415,7 +2415,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: After - name: before in: query @@ -2423,7 +2423,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Before - name: time_range in: query @@ -2431,7 +2431,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: 00:00,24:00 title: Time Range - name: has_clip @@ -2440,7 +2440,7 @@ paths: schema: anyOf: - type: boolean - - type: 'null' + - type: "null" title: Has Clip - name: has_snapshot in: query @@ -2448,7 +2448,7 @@ paths: schema: anyOf: - type: boolean - - type: 'null' + - type: "null" title: Has Snapshot - name: is_submitted in: query @@ -2456,7 +2456,7 @@ paths: schema: anyOf: - type: boolean - - type: 'null' + - type: "null" title: Is Submitted - name: timezone in: query @@ -2464,7 +2464,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: utc title: Timezone - name: min_score @@ -2473,7 +2473,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Min Score - name: max_score in: query @@ -2481,7 +2481,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Max Score - name: min_speed in: query @@ -2489,7 +2489,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Min Speed - name: max_speed in: query @@ -2497,7 +2497,7 @@ paths: schema: anyOf: - type: number - - type: 'null' + - type: "null" title: Max Speed - name: recognized_license_plate in: query @@ -2505,7 +2505,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Recognized License Plate - name: sort @@ -2514,20 +2514,20 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Sort responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/summary: get: tags: @@ -2541,7 +2541,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: utc title: Timezone - name: has_clip @@ -2550,7 +2550,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Has Clip - name: has_snapshot in: query @@ -2558,20 +2558,20 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Has Snapshot responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}: get: tags: @@ -2587,18 +2587,18 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/EventResponse' - '422': + $ref: "#/components/schemas/EventResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" delete: tags: - Events @@ -2615,18 +2615,18 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/retain: post: tags: @@ -2645,18 +2645,18 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" delete: tags: - Events @@ -2674,18 +2674,18 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/plus: post: tags: @@ -2706,20 +2706,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/SubmitPlusBody' + $ref: "#/components/schemas/SubmitPlusBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/EventUploadPlusResponse' - '422': + $ref: "#/components/schemas/EventUploadPlusResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/false_positive: put: tags: @@ -2738,18 +2738,18 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/EventUploadPlusResponse' - '422': + $ref: "#/components/schemas/EventUploadPlusResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/sub_label: post: tags: @@ -2771,20 +2771,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsSubLabelBody' + $ref: "#/components/schemas/EventsSubLabelBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/recognized_license_plate: post: tags: @@ -2806,20 +2806,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsLPRBody' + $ref: "#/components/schemas/EventsLPRBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/description: post: tags: @@ -2841,20 +2841,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsDescriptionBody' + $ref: "#/components/schemas/EventsDescriptionBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/description/regenerate: put: tags: @@ -2876,8 +2876,8 @@ paths: required: false schema: anyOf: - - $ref: '#/components/schemas/RegenerateDescriptionEnum' - - type: 'null' + - $ref: "#/components/schemas/RegenerateDescriptionEnum" + - type: "null" default: thumbnails title: Source - name: force @@ -2886,22 +2886,22 @@ paths: schema: anyOf: - type: boolean - - type: 'null' + - type: "null" default: false title: Force responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /description/generate: post: tags: @@ -2916,20 +2916,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsDescriptionBody' + $ref: "#/components/schemas/EventsDescriptionBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/: delete: tags: @@ -2944,20 +2944,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsDeleteBody' + $ref: "#/components/schemas/EventsDeleteBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/EventMultiDeleteResponse' - '422': + $ref: "#/components/schemas/EventMultiDeleteResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{camera_name}/{label}/create: post: tags: @@ -2987,26 +2987,25 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsCreateBody' + $ref: "#/components/schemas/EventsCreateBody" default: - source_type: api score: 0 duration: 30 include_recording: true draw: {} responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/EventCreateResponse' - '422': + $ref: "#/components/schemas/EventCreateResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/end: put: tags: @@ -3029,20 +3028,20 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/EventsEndBody' + $ref: "#/components/schemas/EventsEndBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: - $ref: '#/components/schemas/GenericResponse' - '422': + $ref: "#/components/schemas/GenericResponse" + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /trigger/embedding: post: tags: @@ -3070,21 +3069,21 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/TriggerEmbeddingBody' + $ref: "#/components/schemas/TriggerEmbeddingBody" responses: - '200': + "200": description: Successful Response content: application/json: schema: type: object title: Response Create Trigger Embedding Trigger Embedding Post - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /trigger/embedding/{camera_name}/{name}: put: tags: @@ -3112,9 +3111,9 @@ paths: content: application/json: schema: - $ref: '#/components/schemas/TriggerEmbeddingBody' + $ref: "#/components/schemas/TriggerEmbeddingBody" responses: - '200': + "200": description: Successful Response content: application/json: @@ -3123,12 +3122,12 @@ paths: title: >- Response Update Trigger Embedding Trigger Embedding Camera Name Name Put - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" delete: tags: - Events @@ -3151,7 +3150,7 @@ paths: type: string title: Name responses: - '200': + "200": description: Successful Response content: application/json: @@ -3160,12 +3159,12 @@ paths: title: >- Response Delete Trigger Embedding Trigger Embedding Camera Name Name Delete - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /triggers/status/{camera_name}: get: tags: @@ -3183,19 +3182,19 @@ paths: type: string title: Camera Name responses: - '200': + "200": description: Successful Response content: application/json: schema: type: object title: Response Get Triggers Status Triggers Status Camera Name Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}: get: tags: @@ -3209,7 +3208,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: fps in: query @@ -3231,7 +3230,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Bbox - name: timestamp in: query @@ -3239,7 +3238,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Timestamp - name: zones in: query @@ -3247,7 +3246,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Zones - name: mask in: query @@ -3255,7 +3254,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Mask - name: motion in: query @@ -3263,7 +3262,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Motion - name: regions in: query @@ -3271,20 +3270,20 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Regions responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/ptz/info: get: tags: @@ -3298,20 +3297,20 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/latest.{extension}: get: tags: @@ -3325,20 +3324,20 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: extension in: path required: true schema: - $ref: '#/components/schemas/Extension' + $ref: "#/components/schemas/Extension" - name: bbox in: query required: false schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Bbox - name: timestamp in: query @@ -3346,7 +3345,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Timestamp - name: zones in: query @@ -3354,7 +3353,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Zones - name: mask in: query @@ -3362,7 +3361,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Mask - name: motion in: query @@ -3370,7 +3369,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Motion - name: paths in: query @@ -3378,7 +3377,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Paths - name: regions in: query @@ -3386,7 +3385,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Regions - name: quality in: query @@ -3394,7 +3393,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 70 title: Quality - name: height @@ -3403,7 +3402,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Height - name: store in: query @@ -3411,20 +3410,20 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Store responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/recordings/{frame_time}/snapshot.{format}: get: tags: @@ -3439,7 +3438,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: frame_time in: path @@ -3463,17 +3462,17 @@ paths: type: integer title: Height responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/plus/{frame_time}: post: tags: @@ -3487,7 +3486,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: frame_time in: path @@ -3496,17 +3495,17 @@ paths: type: string title: Frame Time responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /recordings/storage: get: tags: @@ -3514,7 +3513,7 @@ paths: summary: Get Recordings Storage Usage operationId: get_recordings_storage_usage_recordings_storage_get responses: - '200': + "200": description: Successful Response content: application/json: @@ -3540,21 +3539,21 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" default: all title: Cameras responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/recordings/summary: get: tags: @@ -3569,7 +3568,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: timezone in: query @@ -3579,17 +3578,17 @@ paths: default: utc title: Timezone responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/recordings: get: tags: @@ -3606,7 +3605,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: after in: query @@ -3623,17 +3622,17 @@ paths: default: 1759935670.40172 title: Before responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /recordings/unavailable: get: tags: @@ -3669,7 +3668,7 @@ paths: default: 30 title: Scale responses: - '200': + "200": description: Successful Response content: application/json: @@ -3678,12 +3677,12 @@ paths: items: type: object title: Response No Recordings Recordings Unavailable Get - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/start/{start_ts}/end/{end_ts}/clip.mp4: get: tags: @@ -3700,7 +3699,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: start_ts in: path @@ -3715,17 +3714,17 @@ paths: type: number title: End Ts responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /vod/{camera_name}/start/{start_ts}/end/{end_ts}: get: tags: @@ -3742,7 +3741,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: start_ts in: path @@ -3757,17 +3756,17 @@ paths: type: number title: End Ts responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /vod/{year_month}/{day}/{hour}/{camera_name}: get: tags: @@ -3802,20 +3801,20 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /vod/{year_month}/{day}/{hour}/{camera_name}/{tz_name}: get: tags: @@ -3851,7 +3850,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: tz_name in: path @@ -3860,17 +3859,17 @@ paths: type: string title: Tz Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /vod/event/{event_id}: get: tags: @@ -3897,17 +3896,17 @@ paths: title: Padding description: Padding to apply to the vod. responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/snapshot.jpg: get: tags: @@ -3931,7 +3930,7 @@ paths: schema: anyOf: - type: boolean - - type: 'null' + - type: "null" default: false title: Download - name: timestamp @@ -3940,7 +3939,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Timestamp - name: bbox in: query @@ -3948,7 +3947,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Bbox - name: crop in: query @@ -3956,7 +3955,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Crop - name: height in: query @@ -3964,7 +3963,7 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" title: Height - name: quality in: query @@ -3972,21 +3971,21 @@ paths: schema: anyOf: - type: integer - - type: 'null' + - type: "null" default: 70 title: Quality responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/thumbnail.{extension}: get: tags: @@ -4004,7 +4003,7 @@ paths: in: path required: true schema: - $ref: '#/components/schemas/Extension' + $ref: "#/components/schemas/Extension" - name: max_cache_age in: query required: false @@ -4025,17 +4024,17 @@ paths: default: ios title: Format responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/grid.jpg: get: tags: @@ -4049,7 +4048,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: color in: query @@ -4066,17 +4065,17 @@ paths: default: 0.5 title: Font Scale responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/snapshot-clean.webp: get: tags: @@ -4098,17 +4097,17 @@ paths: default: false title: Download responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/clip.mp4: get: tags: @@ -4132,17 +4131,17 @@ paths: title: Padding description: Padding to apply to clip. responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /events/{event_id}/preview.gif: get: tags: @@ -4157,17 +4156,17 @@ paths: type: string title: Event Id responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/start/{start_ts}/end/{end_ts}/preview.gif: get: tags: @@ -4181,7 +4180,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: start_ts in: path @@ -4205,17 +4204,17 @@ paths: title: Max Cache Age description: Max cache age in seconds. Default 30 days in seconds. responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/start/{start_ts}/end/{end_ts}/preview.mp4: get: tags: @@ -4229,7 +4228,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: start_ts in: path @@ -4253,17 +4252,17 @@ paths: title: Max Cache Age description: Max cache age in seconds. Default 7 days in seconds. responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /review/{event_id}/preview: get: tags: @@ -4288,17 +4287,17 @@ paths: default: gif title: Format responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /preview/{file_name}/thumbnail.webp: get: tags: @@ -4314,17 +4313,17 @@ paths: type: string title: File Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /preview/{file_name}/thumbnail.jpg: get: tags: @@ -4340,17 +4339,17 @@ paths: type: string title: File Name responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/{label}/thumbnail.jpg: get: tags: @@ -4364,7 +4363,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: label in: path @@ -4373,17 +4372,17 @@ paths: type: string title: Label responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/{label}/best.jpg: get: tags: @@ -4397,7 +4396,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: label in: path @@ -4406,17 +4405,17 @@ paths: type: string title: Label responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/{label}/clip.mp4: get: tags: @@ -4430,7 +4429,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: label in: path @@ -4439,17 +4438,17 @@ paths: type: string title: Label responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" /{camera_name}/{label}/snapshot.jpg: get: tags: @@ -4466,7 +4465,7 @@ paths: schema: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera Name - name: label in: path @@ -4475,17 +4474,17 @@ paths: type: string title: Label responses: - '200': + "200": description: Successful Response content: application/json: schema: {} - '422': + "422": description: Validation Error content: application/json: schema: - $ref: '#/components/schemas/HTTPValidationError' + $ref: "#/components/schemas/HTTPValidationError" components: schemas: AppConfigSetBody: @@ -4497,12 +4496,12 @@ components: update_topic: anyOf: - type: string - - type: 'null' + - type: "null" title: Update Topic config_data: anyOf: - type: object - - type: 'null' + - type: "null" title: Config Data type: object title: AppConfigSetBody @@ -4530,7 +4529,7 @@ components: role: anyOf: - type: string - - type: 'null' + - type: "null" title: Role default: viewer type: object @@ -4672,7 +4671,7 @@ components: sub_label: anyOf: - type: string - - type: 'null' + - type: "null" title: Sub Label camera: type: string @@ -4683,12 +4682,12 @@ components: end_time: anyOf: - type: number - - type: 'null' + - type: "null" title: End Time false_positive: anyOf: - type: boolean - - type: 'null' + - type: "null" title: False Positive zones: items: @@ -4698,7 +4697,7 @@ components: thumbnail: anyOf: - type: string - - type: 'null' + - type: "null" title: Thumbnail has_clip: type: boolean @@ -4712,22 +4711,22 @@ components: plus_id: anyOf: - type: string - - type: 'null' + - type: "null" title: Plus Id model_hash: anyOf: - type: string - - type: 'null' + - type: "null" title: Model Hash detector_type: anyOf: - type: string - - type: 'null' + - type: "null" title: Detector Type model_type: anyOf: - type: string - - type: 'null' + - type: "null" title: Model Type data: type: object @@ -4767,39 +4766,33 @@ components: title: EventUploadPlusResponse EventsCreateBody: properties: - source_type: - anyOf: - - type: string - - type: 'null' - title: Source Type - default: api sub_label: anyOf: - type: string - - type: 'null' + - type: "null" title: Sub Label score: anyOf: - type: number - - type: 'null' + - type: "null" title: Score default: 0 duration: anyOf: - type: integer - - type: 'null' + - type: "null" title: Duration default: 30 include_recording: anyOf: - type: boolean - - type: 'null' + - type: "null" title: Include Recording default: true draw: anyOf: - type: object - - type: 'null' + - type: "null" title: Draw default: {} type: object @@ -4820,7 +4813,7 @@ components: description: anyOf: - type: string - - type: 'null' + - type: "null" title: The description of the event type: object required: @@ -4831,7 +4824,7 @@ components: end_time: anyOf: - type: number - - type: 'null' + - type: "null" title: End Time type: object title: EventsEndBody @@ -4846,7 +4839,7 @@ components: - type: number maximum: 1 exclusiveMinimum: 0 - - type: 'null' + - type: "null" title: Score for recognized license plate type: object required: @@ -4863,12 +4856,12 @@ components: - type: number maximum: 1 exclusiveMinimum: 0 - - type: 'null' + - type: "null" title: Score for sub label camera: anyOf: - type: string - - type: 'null' + - type: "null" title: Camera this object is detected on. type: object required: @@ -4918,11 +4911,11 @@ components: ExportRecordingsBody: properties: playback: - $ref: '#/components/schemas/PlaybackFactorEnum' + $ref: "#/components/schemas/PlaybackFactorEnum" title: Playback factor default: realtime source: - $ref: '#/components/schemas/PlaybackSourceEnum' + $ref: "#/components/schemas/PlaybackSourceEnum" title: Playback source default: recordings name: @@ -4961,13 +4954,13 @@ components: score: anyOf: - type: number - - type: 'null' + - type: "null" title: Score description: Confidence score of the recognition (0-1) face_name: anyOf: - type: string - - type: 'null' + - type: "null" title: Face Name description: The recognized face name if successful type: object @@ -5016,7 +5009,7 @@ components: properties: detail: items: - $ref: '#/components/schemas/ValidationError' + $ref: "#/components/schemas/ValidationError" type: array title: Detail type: object @@ -5150,7 +5143,7 @@ components: type: boolean title: Has Been Reviewed severity: - $ref: '#/components/schemas/SeverityEnum' + $ref: "#/components/schemas/SeverityEnum" thumb_path: type: string title: Thumb Path @@ -5170,10 +5163,10 @@ components: ReviewSummaryResponse: properties: last24Hours: - $ref: '#/components/schemas/Last24HoursReview' + $ref: "#/components/schemas/Last24HoursReview" root: additionalProperties: - $ref: '#/components/schemas/DayReview' + $ref: "#/components/schemas/DayReview" type: object title: Root type: object @@ -5200,7 +5193,7 @@ components: export_id: anyOf: - type: string - - type: 'null' + - type: "null" title: Export Id description: The export ID if successfully started type: object @@ -5220,7 +5213,7 @@ components: TriggerEmbeddingBody: properties: type: - $ref: '#/components/schemas/TriggerType' + $ref: "#/components/schemas/TriggerType" data: type: string title: Data diff --git a/frigate/api/defs/request/events_body.py b/frigate/api/defs/request/events_body.py index dd18ff8f7..6110e34f5 100644 --- a/frigate/api/defs/request/events_body.py +++ b/frigate/api/defs/request/events_body.py @@ -29,7 +29,6 @@ class EventsDescriptionBody(BaseModel): class EventsCreateBody(BaseModel): - source_type: Optional[str] = "api" sub_label: Optional[str] = None score: Optional[float] = 0 duration: Optional[int] = 30 diff --git a/frigate/api/event.py b/frigate/api/event.py index b8b596cde..1f5578fae 100644 --- a/frigate/api/event.py +++ b/frigate/api/event.py @@ -1620,7 +1620,7 @@ def create_event( body.score, body.sub_label, body.duration, - body.source_type, + "api", body.draw, ), EventMetadataTypeEnum.manual_event_create.value, From f2ce5572bddc5c44aff8e627c4e6b813b53f7822 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 3 Dec 2025 11:13:27 -0700 Subject: [PATCH 02/16] Don't require state classification models to select all classes --- .../locales/en/views/classificationModel.json | 2 +- .../wizard/Step3ChooseExamples.tsx | 28 +------------------ 2 files changed, 2 insertions(+), 28 deletions(-) diff --git a/web/public/locales/en/views/classificationModel.json b/web/public/locales/en/views/classificationModel.json index 7852bb550..1b1ec811a 100644 --- a/web/public/locales/en/views/classificationModel.json +++ b/web/public/locales/en/views/classificationModel.json @@ -177,7 +177,7 @@ "generateSuccess": "Successfully generated sample images", "missingStatesWarning": { "title": "Missing State Examples", - "description": "You haven't selected examples for all states. The model will not be trained until all states have images. After continuing, use the Recent Classifications view to classify images for the missing states, then train the model." + "description": "It's recommended to select examples for all states for best results. You can continue without selecting all states, but the model will not be trained until all states have images. After continuing, use the Recent Classifications view to classify images for the missing states, then train the model." } } } diff --git a/web/src/components/classification/wizard/Step3ChooseExamples.tsx b/web/src/components/classification/wizard/Step3ChooseExamples.tsx index 47c990071..c4978a1b8 100644 --- a/web/src/components/classification/wizard/Step3ChooseExamples.tsx +++ b/web/src/components/classification/wizard/Step3ChooseExamples.tsx @@ -407,30 +407,6 @@ export default function Step3ChooseExamples({ return allClasses.every((className) => statesWithExamples.has(className)); }, [step1Data.modelType, allClasses, statesWithExamples]); - // For state models on the last class, require all images to be classified - // But allow proceeding even if not all states have examples (with warning) - const canProceed = useMemo(() => { - if (step1Data.modelType === "state" && isLastClass) { - // Check if all 24 images will be classified after current selections are applied - const totalImages = unknownImages.slice(0, 24).length; - - // Count images that will be classified (either already classified or currently selected) - const allImages = unknownImages.slice(0, 24); - const willBeClassified = allImages.filter((img) => { - return imageClassifications[img] || selectedImages.has(img); - }).length; - - return willBeClassified >= totalImages; - } - return true; - }, [ - step1Data.modelType, - isLastClass, - unknownImages, - imageClassifications, - selectedImages, - ]); - const hasUnclassifiedImages = useMemo(() => { if (!unknownImages) return false; const allImages = unknownImages.slice(0, 24); @@ -594,9 +570,7 @@ export default function Step3ChooseExamples({ } variant="select" className="flex items-center justify-center gap-2 sm:flex-1" - disabled={ - !hasGenerated || isGenerating || isProcessing || !canProceed - } + disabled={!hasGenerated || isGenerating || isProcessing} > {isProcessing && } {t("button.continue", { ns: "common" })} From f6a5e9819e9fcfa0c952302cde4802c131afc2b7 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 3 Dec 2025 11:44:08 -0700 Subject: [PATCH 03/16] Specifically validate provided end_time for manual events --- frigate/api/event.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/frigate/api/event.py b/frigate/api/event.py index 1f5578fae..98eaf5886 100644 --- a/frigate/api/event.py +++ b/frigate/api/event.py @@ -1652,10 +1652,27 @@ async def end_event(request: Request, event_id: str, body: EventsEndBody): try: event: Event = Event.get(Event.id == event_id) await require_camera_access(event.camera, request=request) + + if body.end_time is not None and body.end_time < event.start_time: + return JSONResponse( + content=( + { + "success": False, + "message": f"end_time ({body.end_time}) cannot be before start_time ({event.start_time}).", + } + ), + status_code=400, + ) + end_time = body.end_time or datetime.datetime.now().timestamp() request.app.event_metadata_updater.publish( (event_id, end_time), EventMetadataTypeEnum.manual_event_end.value ) + except DoesNotExist: + return JSONResponse( + content=({"success": False, "message": f"Event {event_id} not found."}), + status_code=404, + ) except Exception: return JSONResponse( content=( From a75c2d2abbf5540db124c2d8718fcb6e37328a9e Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 3 Dec 2025 12:55:11 -0700 Subject: [PATCH 04/16] Remove yolov9 specification for warning --- docs/docs/configuration/object_detectors.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/docs/configuration/object_detectors.md b/docs/docs/configuration/object_detectors.md index b02712a16..7050a2296 100644 --- a/docs/docs/configuration/object_detectors.md +++ b/docs/docs/configuration/object_detectors.md @@ -166,7 +166,7 @@ A Tensorflow Lite is provided in the container at `/openvino-model/ssdlite_mobil :::warning -If you are using a Frigate+ YOLOv9 model, you should not define any of the below `model` parameters in your config except for `path`. See [the Frigate+ model docs](/plus/first_model#step-3-set-your-model-id-in-the-config) for more information on setting up your model. +If you are using a Frigate+ model, you should not define any of the below `model` parameters in your config except for `path`. See [the Frigate+ model docs](/plus/first_model#step-3-set-your-model-id-in-the-config) for more information on setting up your model. ::: @@ -408,7 +408,7 @@ The YOLO detector has been designed to support YOLOv3, YOLOv4, YOLOv7, and YOLOv :::warning -If you are using a Frigate+ YOLOv9 model, you should not define any of the below `model` parameters in your config except for `path`. See [the Frigate+ model docs](/plus/first_model#step-3-set-your-model-id-in-the-config) for more information on setting up your model. +If you are using a Frigate+ model, you should not define any of the below `model` parameters in your config except for `path`. See [the Frigate+ model docs](/plus/first_model#step-3-set-your-model-id-in-the-config) for more information on setting up your model. ::: @@ -748,7 +748,7 @@ The YOLO detector has been designed to support YOLOv3, YOLOv4, YOLOv7, and YOLOv :::warning -If you are using a Frigate+ YOLOv9 model, you should not define any of the below `model` parameters in your config except for `path`. See [the Frigate+ model docs](/plus/first_model#step-3-set-your-model-id-in-the-config) for more information on setting up your model. +If you are using a Frigate+ model, you should not define any of the below `model` parameters in your config except for `path`. See [the Frigate+ model docs](/plus/first_model#step-3-set-your-model-id-in-the-config) for more information on setting up your model. ::: From a07d3926782c24068b394d39c60ff38eb510186c Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 3 Dec 2025 13:01:05 -0700 Subject: [PATCH 05/16] Remove warning for coral --- docs/docs/configuration/object_detectors.md | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/docs/configuration/object_detectors.md b/docs/docs/configuration/object_detectors.md index 7050a2296..162e2036b 100644 --- a/docs/docs/configuration/object_detectors.md +++ b/docs/docs/configuration/object_detectors.md @@ -164,12 +164,6 @@ A Tensorflow Lite is provided in the container at `/openvino-model/ssdlite_mobil
YOLOv9 Setup & Config -:::warning - -If you are using a Frigate+ model, you should not define any of the below `model` parameters in your config except for `path`. See [the Frigate+ model docs](/plus/first_model#step-3-set-your-model-id-in-the-config) for more information on setting up your model. - -::: - After placing the downloaded files for the tflite model and labels in your config folder, you can use the following configuration: ```yaml From b71223b79ca0feff10fc4c5250ff91aea67a5d04 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:15:23 -0600 Subject: [PATCH 06/16] clarify zone name tip --- web/public/locales/en/views/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/web/public/locales/en/views/settings.json b/web/public/locales/en/views/settings.json index b08aa10c0..22dae29de 100644 --- a/web/public/locales/en/views/settings.json +++ b/web/public/locales/en/views/settings.json @@ -500,7 +500,7 @@ "name": { "title": "Name", "inputPlaceHolder": "Enter a name…", - "tips": "Name must be at least 2 characters, must have at least one letter, and must not be the name of a camera or another zone." + "tips": "Name must be at least 2 characters, must have at least one letter, and must not be the name of a camera or another zone on this camera." }, "inertia": { "title": "Inertia", From 49be4a53cd41015c73225e790349e8bda52f9983 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:17:41 -0600 Subject: [PATCH 07/16] clarify replace rules in lpr docs --- docs/docs/configuration/license_plate_recognition.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/docs/configuration/license_plate_recognition.md b/docs/docs/configuration/license_plate_recognition.md index c1aa62b22..42ec09bb4 100644 --- a/docs/docs/configuration/license_plate_recognition.md +++ b/docs/docs/configuration/license_plate_recognition.md @@ -107,7 +107,7 @@ Fine-tune the LPR feature using these optional parameters at the global level of ### Normalization Rules -- **`replace_rules`**: List of regex replacement rules to normalize detected plates. These rules are applied sequentially. Each rule must have a `pattern` (which can be a string or a regex, prepended by `r`) and `replacement` (a string, which also supports [backrefs](https://docs.python.org/3/library/re.html#re.sub) like `\1`). These rules are useful for dealing with common OCR issues like noise characters, separators, or confusions (e.g., 'O'→'0'). +- **`replace_rules`**: List of regex replacement rules to normalize detected plates. These rules are applied sequentially and are applied _before_ the `format` regex, if specified. Each rule must have a `pattern` (which can be a string or a regex, prepended by `r`) and `replacement` (a string, which also supports [backrefs](https://docs.python.org/3/library/re.html#re.sub) like `\1`). These rules are useful for dealing with common OCR issues like noise characters, separators, or confusions (e.g., 'O'→'0'). These rules must be defined at the global level of your `lpr` config. From 7450e0a276d43147dd22053eebdaa9af82773e18 Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 3 Dec 2025 14:37:37 -0600 Subject: [PATCH 08/16] remove periods --- docs/static/frigate-api.yaml | 40 ++++++++++++++++++------------------ frigate/api/event.py | 40 ++++++++++++++++++------------------ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/docs/static/frigate-api.yaml b/docs/static/frigate-api.yaml index 1b3e37eb6..f9981f8de 100644 --- a/docs/static/frigate-api.yaml +++ b/docs/static/frigate-api.yaml @@ -2268,7 +2268,7 @@ paths: get: tags: - Events - summary: Get summary of objects. + summary: Get summary of objects description: |- Gets a summary of objects from the database. Returns a list of objects with a max of `limit` objects for each label. @@ -2301,7 +2301,7 @@ paths: get: tags: - Events - summary: Get events by ids. + summary: Get events by ids description: |- Gets events by a list of ids. Returns a list of events. @@ -2333,7 +2333,7 @@ paths: get: tags: - Events - summary: Search events. + summary: Search events description: |- Searches for events in the database. Returns a list of events. @@ -2576,7 +2576,7 @@ paths: get: tags: - Events - summary: Get event by id. + summary: Get event by id description: Gets an event by its id. operationId: event_events__event_id__get parameters: @@ -2602,7 +2602,7 @@ paths: delete: tags: - Events - summary: Delete event. + summary: Delete event description: |- Deletes an event from the database. Returns a success message or an error if the event is not found. @@ -2631,7 +2631,7 @@ paths: post: tags: - Events - summary: Set event retain indefinitely. + summary: Set event retain indefinitely description: |- Sets an event to retain indefinitely. Returns a success message or an error if the event is not found. @@ -2660,7 +2660,7 @@ paths: delete: tags: - Events - summary: Stop event from being retained indefinitely. + summary: Stop event from being retained indefinitely description: |- Stops an event from being retained indefinitely. Returns a success message or an error if the event is not found. @@ -2690,7 +2690,7 @@ paths: post: tags: - Events - summary: Send event to Frigate+. + summary: Send event to Frigate+ description: |- Sends an event to Frigate+. Returns a success message or an error if the event is not found. @@ -2754,7 +2754,7 @@ paths: post: tags: - Events - summary: Set event sub label. + summary: Set event sub label description: |- Sets an event's sub label. Returns a success message or an error if the event is not found. @@ -2789,7 +2789,7 @@ paths: post: tags: - Events - summary: Set event license plate. + summary: Set event license plate description: |- Sets an event's license plate. Returns a success message or an error if the event is not found. @@ -2824,7 +2824,7 @@ paths: post: tags: - Events - summary: Set event description. + summary: Set event description description: |- Sets an event's description. Returns a success message or an error if the event is not found. @@ -2859,7 +2859,7 @@ paths: put: tags: - Events - summary: Regenerate event description. + summary: Regenerate event description description: |- Regenerates an event's description. Returns a success message or an error if the event is not found. @@ -2906,7 +2906,7 @@ paths: post: tags: - Events - summary: Generate description embedding. + summary: Generate description embedding description: |- Generates an embedding for an event's description. Returns a success message or an error if the event is not found. @@ -2934,7 +2934,7 @@ paths: delete: tags: - Events - summary: Delete events. + summary: Delete events description: |- Deletes a list of events from the database. Returns a success message or an error if the events are not found. @@ -2962,7 +2962,7 @@ paths: post: tags: - Events - summary: Create manual event. + summary: Create manual event description: |- Creates a manual event in the database. Returns a success message or an error if the event is not found. @@ -3010,7 +3010,7 @@ paths: put: tags: - Events - summary: End manual event. + summary: End manual event description: |- Ends a manual event. Returns a success message or an error if the event is not found. @@ -3046,7 +3046,7 @@ paths: post: tags: - Events - summary: Create trigger embedding. + summary: Create trigger embedding description: |- Creates a trigger embedding for a specific trigger. Returns a success message or an error if the trigger is not found. @@ -3088,7 +3088,7 @@ paths: put: tags: - Events - summary: Update trigger embedding. + summary: Update trigger embedding description: |- Updates a trigger embedding for a specific trigger. Returns a success message or an error if the trigger is not found. @@ -3131,7 +3131,7 @@ paths: delete: tags: - Events - summary: Delete trigger embedding. + summary: Delete trigger embedding description: |- Deletes a trigger embedding for a specific trigger. Returns a success message or an error if the trigger is not found. @@ -3169,7 +3169,7 @@ paths: get: tags: - Events - summary: Get triggers status. + summary: Get triggers status description: |- Gets the status of all triggers for a specific camera. Returns a success message or an error if the camera is not found. diff --git a/frigate/api/event.py b/frigate/api/event.py index 98eaf5886..fc78ac0e5 100644 --- a/frigate/api/event.py +++ b/frigate/api/event.py @@ -346,7 +346,7 @@ def events( "/events/explore", response_model=list[EventResponse], dependencies=[Depends(allow_any_authenticated())], - summary="Get summary of objects.", + summary="Get summary of objects", description="""Gets a summary of objects from the database. Returns a list of objects with a max of `limit` objects for each label. """, @@ -439,7 +439,7 @@ def events_explore( "/event_ids", response_model=list[EventResponse], dependencies=[Depends(allow_any_authenticated())], - summary="Get events by ids.", + summary="Get events by ids", description="""Gets events by a list of ids. Returns a list of events. """, @@ -473,7 +473,7 @@ async def event_ids(ids: str, request: Request): @router.get( "/events/search", dependencies=[Depends(allow_any_authenticated())], - summary="Search events.", + summary="Search events", description="""Searches for events in the database. Returns a list of events. """, @@ -924,7 +924,7 @@ def events_summary( "/events/{event_id}", response_model=EventResponse, dependencies=[Depends(allow_any_authenticated())], - summary="Get event by id.", + summary="Get event by id", description="Gets an event by its id.", ) async def event(event_id: str, request: Request): @@ -968,7 +968,7 @@ def set_retain(event_id: str): "/events/{event_id}/plus", response_model=EventUploadPlusResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Send event to Frigate+.", + summary="Send event to Frigate+", description="""Sends an event to Frigate+. Returns a success message or an error if the event is not found. """, @@ -1207,7 +1207,7 @@ async def false_positive(request: Request, event_id: str): "/events/{event_id}/retain", response_model=GenericResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Stop event from being retained indefinitely.", + summary="Stop event from being retained indefinitely", description="""Stops an event from being retained indefinitely. Returns a success message or an error if the event is not found. NOTE: This is a legacy endpoint and is not supported in the frontend. @@ -1236,7 +1236,7 @@ async def delete_retain(event_id: str, request: Request): "/events/{event_id}/sub_label", response_model=GenericResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Set event sub label.", + summary="Set event sub label", description="""Sets an event's sub label. Returns a success message or an error if the event is not found. """, @@ -1295,7 +1295,7 @@ async def set_sub_label( "/events/{event_id}/recognized_license_plate", response_model=GenericResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Set event license plate.", + summary="Set event license plate", description="""Sets an event's license plate. Returns a success message or an error if the event is not found. """, @@ -1355,7 +1355,7 @@ async def set_plate( "/events/{event_id}/description", response_model=GenericResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Set event description.", + summary="Set event description", description="""Sets an event's description. Returns a success message or an error if the event is not found. """, @@ -1411,7 +1411,7 @@ async def set_description( "/events/{event_id}/description/regenerate", response_model=GenericResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Regenerate event description.", + summary="Regenerate event description", description="""Regenerates an event's description. Returns a success message or an error if the event is not found. """, @@ -1463,8 +1463,8 @@ async def regenerate_description( @router.post( "/description/generate", response_model=GenericResponse, - # dependencies=[Depends(require_role(["admin"]))], - summary="Generate description embedding.", + dependencies=[Depends(require_role(["admin"]))], + summary="Generate description embedding", description="""Generates an embedding for an event's description. Returns a success message or an error if the event is not found. """, @@ -1529,7 +1529,7 @@ async def delete_single_event(event_id: str, request: Request) -> dict: "/events/{event_id}", response_model=GenericResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Delete event.", + summary="Delete event", description="""Deletes an event from the database. Returns a success message or an error if the event is not found. """, @@ -1544,7 +1544,7 @@ async def delete_event(request: Request, event_id: str): "/events/", response_model=EventMultiDeleteResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Delete events.", + summary="Delete events", description="""Deletes a list of events from the database. Returns a success message or an error if the events are not found. """, @@ -1578,7 +1578,7 @@ async def delete_events(request: Request, body: EventsDeleteBody): "/events/{camera_name}/{label}/create", response_model=EventCreateResponse, dependencies=[Depends(require_role(["admin"]))], - summary="Create manual event.", + summary="Create manual event", description="""Creates a manual event in the database. Returns a success message or an error if the event is not found. NOTES: @@ -1642,7 +1642,7 @@ def create_event( "/events/{event_id}/end", response_model=GenericResponse, dependencies=[Depends(require_role(["admin"]))], - summary="End manual event.", + summary="End manual event", description="""Ends a manual event. Returns a success message or an error if the event is not found. NOTE: This should only be used for manual events. @@ -1691,7 +1691,7 @@ async def end_event(request: Request, event_id: str, body: EventsEndBody): "/trigger/embedding", response_model=dict, dependencies=[Depends(require_role(["admin"]))], - summary="Create trigger embedding.", + summary="Create trigger embedding", description="""Creates a trigger embedding for a specific trigger. Returns a success message or an error if the trigger is not found. """, @@ -1849,7 +1849,7 @@ def create_trigger_embedding( "/trigger/embedding/{camera_name}/{name}", response_model=dict, dependencies=[Depends(require_role(["admin"]))], - summary="Update trigger embedding.", + summary="Update trigger embedding", description="""Updates a trigger embedding for a specific trigger. Returns a success message or an error if the trigger is not found. """, @@ -2014,7 +2014,7 @@ def update_trigger_embedding( "/trigger/embedding/{camera_name}/{name}", response_model=dict, dependencies=[Depends(require_role(["admin"]))], - summary="Delete trigger embedding.", + summary="Delete trigger embedding", description="""Deletes a trigger embedding for a specific trigger. Returns a success message or an error if the trigger is not found. """, @@ -2088,7 +2088,7 @@ def delete_trigger_embedding( "/triggers/status/{camera_name}", response_model=dict, dependencies=[Depends(require_role(["admin"]))], - summary="Get triggers status.", + summary="Get triggers status", description="""Gets the status of all triggers for a specific camera. Returns a success message or an error if the camera is not found. """, From f25f1f689b68642098295ab629752463a9df4515 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Wed, 3 Dec 2025 13:53:54 -0700 Subject: [PATCH 09/16] Add explanation for review report --- docs/docs/configuration/genai/review_summaries.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/docs/configuration/genai/review_summaries.md b/docs/docs/configuration/genai/review_summaries.md index 4e8107441..e83578490 100644 --- a/docs/docs/configuration/genai/review_summaries.md +++ b/docs/docs/configuration/genai/review_summaries.md @@ -111,3 +111,9 @@ review: ## Review Reports Along with individual review item summaries, Generative AI provides the ability to request a report of a given time period. For example, you can get a daily report while on a vacation of any suspicious activity or other concerns that may require review. + +### Requesting Reports Programmatically + +Review reports can be requested via the [API](/integrations/api#review-summarization) by sending a POST request to `/api/review/summarize/start/{start_ts}/end/{end_ts}` with Unix timestamps. + +For Home Assistant users, there is a built-in service (`frigate.generate_review_summary`) that makes it easy to request review reports as part of automations or scripts. This allows you to automatically generate daily summaries, vacation reports, or custom time period reports based on your specific needs. From 87e67d22e20c74a634c47fefa46c92c22609146f Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 3 Dec 2025 21:44:02 -0600 Subject: [PATCH 10/16] adjust HLS gap controller params defaults to false, should help to recover from hangs and stalling in tracking details videos on chrome --- .../overlay/detail/TrackingDetails.tsx | 1 + web/src/components/player/HlsVideoPlayer.tsx | 28 ++++++++++++++++--- 2 files changed, 25 insertions(+), 4 deletions(-) diff --git a/web/src/components/overlay/detail/TrackingDetails.tsx b/web/src/components/overlay/detail/TrackingDetails.tsx index fa2f0cb2b..2cdd330ac 100644 --- a/web/src/components/overlay/detail/TrackingDetails.tsx +++ b/web/src/components/overlay/detail/TrackingDetails.tsx @@ -559,6 +559,7 @@ export function TrackingDetails({ isDetailMode={true} camera={event.camera} currentTimeOverride={currentTime} + enableGapControllerRecovery={true} /> {isVideoLoading && ( diff --git a/web/src/components/player/HlsVideoPlayer.tsx b/web/src/components/player/HlsVideoPlayer.tsx index 045b8366f..aabd93ac8 100644 --- a/web/src/components/player/HlsVideoPlayer.tsx +++ b/web/src/components/player/HlsVideoPlayer.tsx @@ -5,7 +5,7 @@ import { useRef, useState, } from "react"; -import Hls from "hls.js"; +import Hls, { HlsConfig } from "hls.js"; import { isDesktop, isMobile } from "react-device-detect"; import { TransformComponent, TransformWrapper } from "react-zoom-pan-pinch"; import VideoControls from "./VideoControls"; @@ -57,6 +57,7 @@ type HlsVideoPlayerProps = { isDetailMode?: boolean; camera?: string; currentTimeOverride?: number; + enableGapControllerRecovery?: boolean; }; export default function HlsVideoPlayer({ @@ -81,6 +82,7 @@ export default function HlsVideoPlayer({ isDetailMode = false, camera, currentTimeOverride, + enableGapControllerRecovery = false, }: HlsVideoPlayerProps) { const { t } = useTranslation("components/player"); const { data: config } = useSWR("config"); @@ -170,11 +172,23 @@ export default function HlsVideoPlayer({ return; } - hlsRef.current = new Hls({ + // Base HLS configuration + const baseConfig: Partial = { maxBufferLength: 10, maxBufferSize: 20 * 1000 * 1000, startPosition: currentSource.startPosition, - }); + }; + + const hlsConfig = { ...baseConfig }; + + if (enableGapControllerRecovery) { + hlsConfig.highBufferWatchdogPeriod = 1; // Check for stalls every 1 second (default: 3) + hlsConfig.nudgeOffset = 0.2; // Nudge playhead forward 0.2s when stalled (default: 0.1) + hlsConfig.nudgeMaxRetry = 5; // Try up to 5 nudges before giving up (default: 3) + hlsConfig.maxBufferHole = 0.5; // Tolerate up to 0.5s gaps between fragments (default: 0.1) + } + + hlsRef.current = new Hls(hlsConfig); hlsRef.current.attachMedia(videoRef.current); hlsRef.current.loadSource(currentSource.playlist); videoRef.current.playbackRate = currentPlaybackRate; @@ -187,7 +201,13 @@ export default function HlsVideoPlayer({ hlsRef.current.destroy(); } }; - }, [videoRef, hlsRef, useHlsCompat, currentSource]); + }, [ + videoRef, + hlsRef, + useHlsCompat, + currentSource, + enableGapControllerRecovery, + ]); // state handling From 130dc76a01bc5685ed6ba3924f7437d78f8ca72c Mon Sep 17 00:00:00 2001 From: Josh Hawkins <32435876+hawkeye217@users.noreply.github.com> Date: Wed, 3 Dec 2025 21:59:57 -0600 Subject: [PATCH 11/16] only redirect to login page once on 401 attempt to fix ios pwa safari redirect storm --- web/src/api/index.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/web/src/api/index.tsx b/web/src/api/index.tsx index a9044a6d7..540a328eb 100644 --- a/web/src/api/index.tsx +++ b/web/src/api/index.tsx @@ -6,6 +6,10 @@ import { ReactNode } from "react"; axios.defaults.baseURL = `${baseUrl}api/`; +// Module-level flag to prevent multiple simultaneous redirects +// (eg, when multiple SWR queries fail with 401 at once) +let isRedirectingToLogin = false; + type ApiProviderType = { children?: ReactNode; options?: Record; @@ -31,7 +35,8 @@ export function ApiProvider({ children, options }: ApiProviderType) { ) { // redirect to the login page if not already there const loginPage = error.response.headers.get("location") ?? "login"; - if (window.location.href !== loginPage) { + if (window.location.href !== loginPage && !isRedirectingToLogin) { + isRedirectingToLogin = true; window.location.href = loginPage; } } From 12e5f274dda9d86c4f287f2c7633a828946f36c9 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Thu, 4 Dec 2025 09:00:37 -0700 Subject: [PATCH 12/16] Use contextual information from other cameras to inform report summary --- .../post/review_descriptions.py | 83 +++++++++++++++---- frigate/genai/__init__.py | 21 ++++- 2 files changed, 86 insertions(+), 18 deletions(-) diff --git a/frigate/data_processing/post/review_descriptions.py b/frigate/data_processing/post/review_descriptions.py index 60788e504..23317baba 100644 --- a/frigate/data_processing/post/review_descriptions.py +++ b/frigate/data_processing/post/review_descriptions.py @@ -209,10 +209,22 @@ class ReviewDescriptionProcessor(PostProcessorApi): logger.debug( f"Found GenAI Review Summary request for {start_ts} to {end_ts}" ) - items: list[dict[str, Any]] = [ - r["data"]["metadata"] + + # Query all review segments with camera and time information + segments: list[dict[str, Any]] = [ + { + "camera": r["camera"], + "start_time": r["start_time"], + "end_time": r["end_time"], + "metadata": r["data"]["metadata"], + } for r in ( - ReviewSegment.select(ReviewSegment.data) + ReviewSegment.select( + ReviewSegment.camera, + ReviewSegment.start_time, + ReviewSegment.end_time, + ReviewSegment.data, + ) .where( (ReviewSegment.data["metadata"].is_null(False)) & (ReviewSegment.start_time < end_ts) @@ -224,21 +236,64 @@ class ReviewDescriptionProcessor(PostProcessorApi): ) ] - if len(items) == 0: + if len(segments) == 0: logger.debug("No review items with metadata found during time period") - return "No activity was found during this time." + return "No activity was found during this time period." - important_items = list( - filter( - lambda item: item.get("potential_threat_level", 0) > 0 - or item.get("other_concerns"), - items, - ) - ) + # Identify primary items (important items that need review) + primary_segments = [ + seg + for seg in segments + if seg["metadata"].get("potential_threat_level", 0) > 0 + or seg["metadata"].get("other_concerns") + ] - if not important_items: + if not primary_segments: return "No concerns were found during this time period." + # For each primary segment, find overlapping contextual items from other cameras + all_items_for_summary = [] + + for primary_seg in primary_segments: + # Add the primary item with marker + primary_item = copy.deepcopy(primary_seg["metadata"]) + primary_item["_is_primary"] = True + primary_item["_camera"] = primary_seg["camera"] + all_items_for_summary.append(primary_item) + + # Find overlapping contextual items from other cameras + primary_start = primary_seg["start_time"] + primary_end = primary_seg["end_time"] + primary_camera = primary_seg["camera"] + + for seg in segments: + if seg["camera"] == primary_camera: + continue + + if seg in primary_segments: + continue + + seg_start = seg["start_time"] + seg_end = seg["end_time"] + + if seg_start < primary_end and primary_start < seg_end: + contextual_item = copy.deepcopy(seg["metadata"]) + contextual_item["_is_primary"] = False + contextual_item["_camera"] = seg["camera"] + contextual_item["_related_to_camera"] = primary_camera + + if not any( + item.get("_camera") == seg["camera"] + and item.get("time") == contextual_item.get("time") + for item in all_items_for_summary + ): + all_items_for_summary.append(contextual_item) + + logger.debug( + f"Summary includes {len(primary_segments)} primary items and " + f"{len(all_items_for_summary) - len(primary_segments)} contextual items" + ) + if self.config.review.genai.debug_save_thumbnails: Path( os.path.join(CLIPS_DIR, "genai-requests", f"{start_ts}-{end_ts}") @@ -247,7 +302,7 @@ class ReviewDescriptionProcessor(PostProcessorApi): return self.genai_client.generate_review_summary( start_ts, end_ts, - important_items, + all_items_for_summary, self.config.review.genai.debug_save_thumbnails, ) else: diff --git a/frigate/genai/__init__.py b/frigate/genai/__init__.py index d86e3cbc5..2c9a9f027 100644 --- a/frigate/genai/__init__.py +++ b/frigate/genai/__init__.py @@ -185,10 +185,17 @@ Each line represents a detection state, not necessarily unique individuals. Pare timeline_summary_prompt = f""" You are a security officer. Time range: {time_range}. -Input: JSON list with "title", "scene", "confidence", "potential_threat_level" (1-2), "other_concerns". +Input: JSON list with "title", "scene", "confidence", "potential_threat_level" (0-2), "other_concerns", "_is_primary", "_camera". Task: Write a concise, human-presentable security report in markdown format. +Important - Understanding Primary vs Contextual Items: +- Items with "_is_primary": true are events that require review or attention +- Items with "_is_primary": false are additional context from other camera perspectives that occurred at the same time +- Contextual items (threat level 0) provide important background information to help understand primary events +- Use contextual items to provide a more complete and accurate understanding of what actually happened +- The "_camera" field indicates which camera captured each event + Rules for the report: - Title & overview @@ -198,31 +205,37 @@ Rules for the report: - Event details - Present events in chronological order as a bullet list. + - **When primary and contextual items occur at overlapping times, COMBINE them into a single comprehensive bullet.** + - Use the contextual information to provide a more complete picture of what happened. - **If multiple events occur within the same minute or overlapping time range, COMBINE them into a single bullet.** - Summarize the distinct activities as sub-points under the shared timestamp. - - If no timestamp is given, preserve order but label as “Time not specified.” + - If no timestamp is given, preserve order but label as "Time not specified." - Use bold timestamps for clarity. + - Include camera names when multiple cameras captured related activity. - Group bullets under subheadings when multiple events fall into the same category (e.g., Vehicle Activity, Porch Activity, Unusual Behavior). - Threat levels - - Always show the threat level for each event using these labels: + - Always show the threat level for PRIMARY events using these labels: - Threat level 0: "Normal" - Threat level 1: "Needs review" - Threat level 2: "Security concern" - Format as (threat level: Normal), (threat level: Needs review), or (threat level: Security concern). + - When contextual items help explain a primary event, adjust your description to reflect the fuller context. - If multiple events at the same time share the same threat level, only state it once. - Final assessment - End with a Final Assessment section. - - If all events are threat level 0: + - If all primary events are threat level 0 or explained by contextual items: Final assessment: Only normal residential activity observed during this period. - If threat level 1 events are present: Final assessment: Some activity requires review but no security concerns identified. - If threat level 2 events are present, clearly summarize them as Security concerns requiring immediate attention. + - Note if contextual information from other cameras provided clarity about seemingly suspicious activity. - Conciseness - Do not repeat benign clothing/appearance details unless they distinguish individuals. - Summarize similar routine events instead of restating full scene descriptions. + - When contextual items simply confirm what the primary event already described, keep the description brief. """ for item in segments: From eb75c76ed40153d27080fae10cddea8b4d4d7387 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Thu, 4 Dec 2025 09:09:06 -0700 Subject: [PATCH 13/16] Formatting and prompt improvements for review summary report --- .../post/review_descriptions.py | 10 +++--- frigate/genai/__init__.py | 35 ++++++++++--------- 2 files changed, 25 insertions(+), 20 deletions(-) diff --git a/frigate/data_processing/post/review_descriptions.py b/frigate/data_processing/post/review_descriptions.py index 23317baba..7965490fa 100644 --- a/frigate/data_processing/post/review_descriptions.py +++ b/frigate/data_processing/post/review_descriptions.py @@ -213,7 +213,7 @@ class ReviewDescriptionProcessor(PostProcessorApi): # Query all review segments with camera and time information segments: list[dict[str, Any]] = [ { - "camera": r["camera"], + "camera": r["camera"].replace("_", " ").title(), "start_time": r["start_time"], "end_time": r["end_time"], "metadata": r["data"]["metadata"], @@ -267,7 +267,9 @@ class ReviewDescriptionProcessor(PostProcessorApi): primary_camera = primary_seg["camera"] for seg in segments: - if seg["camera"] == primary_camera: + seg_camera = seg["camera"] + + if seg_camera == primary_camera: continue if seg in primary_segments: @@ -279,11 +281,11 @@ class ReviewDescriptionProcessor(PostProcessorApi): if seg_start < primary_end and primary_start < seg_end: contextual_item = copy.deepcopy(seg["metadata"]) contextual_item["_is_primary"] = False - contextual_item["_camera"] = seg["camera"] + contextual_item["_camera"] = seg_camera contextual_item["_related_to_camera"] = primary_camera if not any( - item.get("_camera") == seg["camera"] + item.get("_camera") == seg_camera and item.get("time") == contextual_item.get("time") for item in all_items_for_summary ): diff --git a/frigate/genai/__init__.py b/frigate/genai/__init__.py index 2c9a9f027..79c4ff62b 100644 --- a/frigate/genai/__init__.py +++ b/frigate/genai/__init__.py @@ -189,12 +189,13 @@ Input: JSON list with "title", "scene", "confidence", "potential_threat_level" ( Task: Write a concise, human-presentable security report in markdown format. -Important - Understanding Primary vs Contextual Items: -- Items with "_is_primary": true are events that require review or attention -- Items with "_is_primary": false are additional context from other camera perspectives that occurred at the same time -- Contextual items (threat level 0) provide important background information to help understand primary events -- Use contextual items to provide a more complete and accurate understanding of what actually happened +CRITICAL - Understanding Primary vs Contextual Items: +- Items with "_is_primary": true are events that REQUIRE REVIEW and MUST be included in the report +- Items with "_is_primary": false are additional context from other camera perspectives +- **DO NOT create separate bullet points or sections for contextual items** +- **ONLY use contextual items to enrich and inform the description of primary items** - The "_camera" field indicates which camera captured each event +- When a contextual item provides relevant background (e.g., delivery truck explaining person at door), incorporate that information directly into the primary event's description Rules for the report: @@ -204,15 +205,16 @@ Rules for the report: - Write a 1-2 sentence situational overview capturing the general pattern of the period. - Event details - - Present events in chronological order as a bullet list. - - **When primary and contextual items occur at overlapping times, COMBINE them into a single comprehensive bullet.** - - Use the contextual information to provide a more complete picture of what happened. - - **If multiple events occur within the same minute or overlapping time range, COMBINE them into a single bullet.** - - Summarize the distinct activities as sub-points under the shared timestamp. + - **ONLY create bullet points for PRIMARY items (_is_primary: true)** + - Do NOT create separate bullets for contextual items + - Present primary events in chronological order as a bullet list. + - When contextual items overlap with a primary event, weave that information naturally into the primary event's description. + - Example: Instead of "Person at door" write "Person at door (delivery driver, as delivery truck was present on driveway camera)" + - If multiple PRIMARY events occur within the same minute, combine them into a single bullet with sub-points. - If no timestamp is given, preserve order but label as "Time not specified." - Use bold timestamps for clarity. - - Include camera names when multiple cameras captured related activity. - - Group bullets under subheadings when multiple events fall into the same category (e.g., Vehicle Activity, Porch Activity, Unusual Behavior). + - Include the primary event's camera name. + - Group bullets under subheadings when multiple PRIMARY events fall into the same category (e.g., Porch Activity, Unusual Behavior). - Threat levels - Always show the threat level for PRIMARY events using these labels: @@ -220,8 +222,8 @@ Rules for the report: - Threat level 1: "Needs review" - Threat level 2: "Security concern" - Format as (threat level: Normal), (threat level: Needs review), or (threat level: Security concern). - - When contextual items help explain a primary event, adjust your description to reflect the fuller context. - - If multiple events at the same time share the same threat level, only state it once. + - When contextual items explain or reduce concern about a primary event, the description should reflect this understanding. + - If multiple PRIMARY events at the same time share the same threat level, only state it once. - Final assessment - End with a Final Assessment section. @@ -230,12 +232,13 @@ Rules for the report: - If threat level 1 events are present: Final assessment: Some activity requires review but no security concerns identified. - If threat level 2 events are present, clearly summarize them as Security concerns requiring immediate attention. - - Note if contextual information from other cameras provided clarity about seemingly suspicious activity. + - Keep this section brief - do not repeat details from the event descriptions above. - Conciseness - Do not repeat benign clothing/appearance details unless they distinguish individuals. - Summarize similar routine events instead of restating full scene descriptions. - - When contextual items simply confirm what the primary event already described, keep the description brief. + - When incorporating contextual information, do so briefly and naturally within the primary event description. + - Avoid lengthy explanatory notes - integrate context seamlessly into the narrative. """ for item in segments: From 7544d9caf89d3ba9cf6cfdabd1d9444b47daa583 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Thu, 4 Dec 2025 09:18:29 -0700 Subject: [PATCH 14/16] More improvements to prompt --- frigate/genai/__init__.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/frigate/genai/__init__.py b/frigate/genai/__init__.py index 79c4ff62b..f3ebeb57b 100644 --- a/frigate/genai/__init__.py +++ b/frigate/genai/__init__.py @@ -191,11 +191,13 @@ Task: Write a concise, human-presentable security report in markdown format. CRITICAL - Understanding Primary vs Contextual Items: - Items with "_is_primary": true are events that REQUIRE REVIEW and MUST be included in the report -- Items with "_is_primary": false are additional context from other camera perspectives +- Items with "_is_primary": false are additional context from other camera perspectives that overlap in time - **DO NOT create separate bullet points or sections for contextual items** - **ONLY use contextual items to enrich and inform the description of primary items** - The "_camera" field indicates which camera captured each event -- When a contextual item provides relevant background (e.g., delivery truck explaining person at door), incorporate that information directly into the primary event's description +- **When a contextual item provides relevant background, you MUST incorporate it directly into the primary event's bullet point** +- Contextual information often explains or de-escalates seemingly suspicious primary events +- Example: If primary shows "person at door with face covering" and context shows "delivery truck present", describe it as "delivery person at door (delivery truck visible on driveway camera)" Rules for the report: @@ -203,26 +205,32 @@ Rules for the report: - Start with: # Security Summary - {time_range} - Write a 1-2 sentence situational overview capturing the general pattern of the period. + - Keep the overview high-level; specific details will be in the event bullets below. - Event details - **ONLY create bullet points for PRIMARY items (_is_primary: true)** + - **Do NOT create sections or bullets for events that don't exist** - Do NOT create separate bullets for contextual items - Present primary events in chronological order as a bullet list. - - When contextual items overlap with a primary event, weave that information naturally into the primary event's description. - - Example: Instead of "Person at door" write "Person at door (delivery driver, as delivery truck was present on driveway camera)" + - **CRITICAL: When contextual items overlap with a primary event, you MUST weave that information directly into the same bullet point** + - Format: **[Timestamp]** - [Description incorporating any contextual information]. [Camera info]. (threat level: X) + - Example: "**5:59 PM** - Delivery person approached porch and left package, while delivery truck was visible in driveway (Front Driveway Cam shows truck). Camera: Front Door Cam. (threat level: Normal)" + - If contextual information provides an explanation (e.g., delivery truck → person is likely delivery driver), reflect this understanding in your description and potentially adjust the perceived threat level - If multiple PRIMARY events occur within the same minute, combine them into a single bullet with sub-points. - - If no timestamp is given, preserve order but label as "Time not specified." - Use bold timestamps for clarity. - - Include the primary event's camera name. - - Group bullets under subheadings when multiple PRIMARY events fall into the same category (e.g., Porch Activity, Unusual Behavior). + - Camera format: "Camera: [camera name]" or mention contextual cameras inline when relevant + - Group bullets under subheadings ONLY when you have actual PRIMARY events to list (e.g., Porch Activity, Unusual Behavior). - Threat levels - - Always show the threat level for PRIMARY events using these labels: + - Show the threat level for PRIMARY events using these labels: - Threat level 0: "Normal" - Threat level 1: "Needs review" - Threat level 2: "Security concern" - Format as (threat level: Normal), (threat level: Needs review), or (threat level: Security concern). - - When contextual items explain or reduce concern about a primary event, the description should reflect this understanding. + - **When contextual items clearly explain a primary event (e.g., delivery truck explains person at door), you should describe it as normal activity and note the explanation** + - **Your description and tone should reflect the fuller understanding provided by contextual information** + - Example: Primary event says "unidentified person with face covering" but context shows delivery truck → describe as "delivery person (truck visible on Front Driveway Cam)" rather than emphasizing suspicious elements + - The stored threat level remains as originally classified, but your narrative should reflect the contextual understanding - If multiple PRIMARY events at the same time share the same threat level, only state it once. - Final assessment From b3abede6cb648aed97b1f2668ebde91c01696441 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Thu, 4 Dec 2025 09:50:25 -0700 Subject: [PATCH 15/16] Remove examples --- frigate/genai/__init__.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/frigate/genai/__init__.py b/frigate/genai/__init__.py index f3ebeb57b..05c8d3926 100644 --- a/frigate/genai/__init__.py +++ b/frigate/genai/__init__.py @@ -197,7 +197,6 @@ CRITICAL - Understanding Primary vs Contextual Items: - The "_camera" field indicates which camera captured each event - **When a contextual item provides relevant background, you MUST incorporate it directly into the primary event's bullet point** - Contextual information often explains or de-escalates seemingly suspicious primary events -- Example: If primary shows "person at door with face covering" and context shows "delivery truck present", describe it as "delivery person at door (delivery truck visible on driveway camera)" Rules for the report: @@ -214,7 +213,6 @@ Rules for the report: - Present primary events in chronological order as a bullet list. - **CRITICAL: When contextual items overlap with a primary event, you MUST weave that information directly into the same bullet point** - Format: **[Timestamp]** - [Description incorporating any contextual information]. [Camera info]. (threat level: X) - - Example: "**5:59 PM** - Delivery person approached porch and left package, while delivery truck was visible in driveway (Front Driveway Cam shows truck). Camera: Front Door Cam. (threat level: Normal)" - If contextual information provides an explanation (e.g., delivery truck → person is likely delivery driver), reflect this understanding in your description and potentially adjust the perceived threat level - If multiple PRIMARY events occur within the same minute, combine them into a single bullet with sub-points. - Use bold timestamps for clarity. From bbe18d5d6bc83c24667d2e7eb442e0b3186617c3 Mon Sep 17 00:00:00 2001 From: Nicolas Mowen Date: Thu, 4 Dec 2025 10:32:45 -0700 Subject: [PATCH 16/16] Don't show admin action buttons on export card --- web/src/components/card/ExportCard.tsx | 36 ++++++++++++++------------ 1 file changed, 20 insertions(+), 16 deletions(-) diff --git a/web/src/components/card/ExportCard.tsx b/web/src/components/card/ExportCard.tsx index d95c6f318..021524532 100644 --- a/web/src/components/card/ExportCard.tsx +++ b/web/src/components/card/ExportCard.tsx @@ -23,6 +23,7 @@ import { useTranslation } from "react-i18next"; import { ImageShadowOverlay } from "../overlay/ImageShadowOverlay"; import BlurredIconButton from "../button/BlurredIconButton"; import { Tooltip, TooltipContent, TooltipTrigger } from "../ui/tooltip"; +import { useIsAdmin } from "@/hooks/use-is-admin"; type ExportProps = { className: string; @@ -40,6 +41,7 @@ export default function ExportCard({ onDelete, }: ExportProps) { const { t } = useTranslation(["views/exports"]); + const isAdmin = useIsAdmin(); const [hovered, setHovered] = useState(false); const [loading, setLoading] = useState( exportedRecording.thumb_path.length > 0, @@ -195,7 +197,7 @@ export default function ExportCard({ )} - {!exportedRecording.in_progress && ( + {isAdmin && !exportedRecording.in_progress && ( {t("tooltip.editName")} )} - - - - onDelete({ - file: exportedRecording.id, - exportName: exportedRecording.name, - }) - } - > - - - - {t("tooltip.deleteExport")} - + {isAdmin && ( + + + + onDelete({ + file: exportedRecording.id, + exportName: exportedRecording.name, + }) + } + > + + + + {t("tooltip.deleteExport")} + + )}