mirror of
https://github.com/blakeblackshear/frigate.git
synced 2024-11-21 19:07:46 +01:00
Use custom body for the export recordings endpoint (#14908)
* Use custom body for the export recordings endpoint * Fixed usage of ExportRecordingsBody * Updated docs to reflect changes to export endpoint * Fix friendly name and source * Updated openAPI spec
This commit is contained in:
parent
64b3397f8e
commit
d2b2f3d54d
90
docs/static/frigate-api.yaml
vendored
90
docs/static/frigate-api.yaml
vendored
@ -7,7 +7,7 @@ info:
|
|||||||
|
|
||||||
servers:
|
servers:
|
||||||
- url: https://demo.frigate.video/api
|
- url: https://demo.frigate.video/api
|
||||||
- url: http://localhost:5001/
|
- url: http://localhost:5001/api
|
||||||
|
|
||||||
paths:
|
paths:
|
||||||
/auth:
|
/auth:
|
||||||
@ -296,7 +296,7 @@ paths:
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ReviewSetMultipleReviewedBody'
|
$ref: '#/components/schemas/ReviewModifyMultipleBody'
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Successful Response
|
description: Successful Response
|
||||||
@ -321,7 +321,7 @@ paths:
|
|||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
$ref: '#/components/schemas/ReviewDeleteMultipleReviewsBody'
|
$ref: '#/components/schemas/ReviewModifyMultipleBody'
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Successful Response
|
description: Successful Response
|
||||||
@ -1141,11 +1141,11 @@ paths:
|
|||||||
type: number
|
type: number
|
||||||
title: End Time
|
title: End Time
|
||||||
requestBody:
|
requestBody:
|
||||||
|
required: true
|
||||||
content:
|
content:
|
||||||
application/json:
|
application/json:
|
||||||
schema:
|
schema:
|
||||||
type: object
|
$ref: '#/components/schemas/ExportRecordingsBody'
|
||||||
title: Body
|
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
description: Successful Response
|
description: Successful Response
|
||||||
@ -1408,6 +1408,14 @@ paths:
|
|||||||
- type: number
|
- type: number
|
||||||
- type: 'null'
|
- type: 'null'
|
||||||
title: Max Length
|
title: Max Length
|
||||||
|
- name: event_id
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
anyOf:
|
||||||
|
- type: string
|
||||||
|
- type: 'null'
|
||||||
|
title: Event Id
|
||||||
- name: sort
|
- name: sort
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
@ -1518,7 +1526,7 @@ paths:
|
|||||||
anyOf:
|
anyOf:
|
||||||
- type: string
|
- type: string
|
||||||
- type: 'null'
|
- type: 'null'
|
||||||
default: thumbnail,description
|
default: thumbnail
|
||||||
title: Search Type
|
title: Search Type
|
||||||
- name: include_thumbnails
|
- name: include_thumbnails
|
||||||
in: query
|
in: query
|
||||||
@ -1590,6 +1598,22 @@ paths:
|
|||||||
- type: 'null'
|
- type: 'null'
|
||||||
default: 00:00,24:00
|
default: 00:00,24:00
|
||||||
title: Time Range
|
title: Time Range
|
||||||
|
- name: has_clip
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
anyOf:
|
||||||
|
- type: boolean
|
||||||
|
- type: 'null'
|
||||||
|
title: Has Clip
|
||||||
|
- name: has_snapshot
|
||||||
|
in: query
|
||||||
|
required: false
|
||||||
|
schema:
|
||||||
|
anyOf:
|
||||||
|
- type: boolean
|
||||||
|
- type: 'null'
|
||||||
|
title: Has Snapshot
|
||||||
- name: timezone
|
- name: timezone
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
@ -2356,14 +2380,14 @@ paths:
|
|||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
type: number
|
type: number
|
||||||
default: 1729274204.653048
|
default: 1731275308.238304
|
||||||
title: After
|
title: After
|
||||||
- name: before
|
- name: before
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
schema:
|
schema:
|
||||||
type: number
|
type: number
|
||||||
default: 1729277804.653095
|
default: 1731278908.238313
|
||||||
title: Before
|
title: Before
|
||||||
responses:
|
responses:
|
||||||
'200':
|
'200':
|
||||||
@ -3262,6 +3286,27 @@ components:
|
|||||||
required:
|
required:
|
||||||
- subLabel
|
- subLabel
|
||||||
title: EventsSubLabelBody
|
title: EventsSubLabelBody
|
||||||
|
ExportRecordingsBody:
|
||||||
|
properties:
|
||||||
|
playback:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/PlaybackFactorEnum'
|
||||||
|
title: Playback factor
|
||||||
|
default: realtime
|
||||||
|
source:
|
||||||
|
allOf:
|
||||||
|
- $ref: '#/components/schemas/PlaybackSourceEnum'
|
||||||
|
title: Playback source
|
||||||
|
default: recordings
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
maxLength: 256
|
||||||
|
title: Friendly name
|
||||||
|
image_path:
|
||||||
|
type: string
|
||||||
|
title: Image Path
|
||||||
|
type: object
|
||||||
|
title: ExportRecordingsBody
|
||||||
Extension:
|
Extension:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
@ -3313,6 +3358,18 @@ components:
|
|||||||
- total_alert
|
- total_alert
|
||||||
- total_detection
|
- total_detection
|
||||||
title: Last24HoursReview
|
title: Last24HoursReview
|
||||||
|
PlaybackFactorEnum:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- realtime
|
||||||
|
- timelapse_25x
|
||||||
|
title: PlaybackFactorEnum
|
||||||
|
PlaybackSourceEnum:
|
||||||
|
type: string
|
||||||
|
enum:
|
||||||
|
- recordings
|
||||||
|
- preview
|
||||||
|
title: PlaybackSourceEnum
|
||||||
RegenerateDescriptionEnum:
|
RegenerateDescriptionEnum:
|
||||||
type: string
|
type: string
|
||||||
enum:
|
enum:
|
||||||
@ -3336,7 +3393,7 @@ components:
|
|||||||
- motion
|
- motion
|
||||||
- camera
|
- camera
|
||||||
title: ReviewActivityMotionResponse
|
title: ReviewActivityMotionResponse
|
||||||
ReviewDeleteMultipleReviewsBody:
|
ReviewModifyMultipleBody:
|
||||||
properties:
|
properties:
|
||||||
ids:
|
ids:
|
||||||
items:
|
items:
|
||||||
@ -3348,7 +3405,7 @@ components:
|
|||||||
type: object
|
type: object
|
||||||
required:
|
required:
|
||||||
- ids
|
- ids
|
||||||
title: ReviewDeleteMultipleReviewsBody
|
title: ReviewModifyMultipleBody
|
||||||
ReviewSegmentResponse:
|
ReviewSegmentResponse:
|
||||||
properties:
|
properties:
|
||||||
id:
|
id:
|
||||||
@ -3386,19 +3443,6 @@ components:
|
|||||||
- thumb_path
|
- thumb_path
|
||||||
- data
|
- data
|
||||||
title: ReviewSegmentResponse
|
title: ReviewSegmentResponse
|
||||||
ReviewSetMultipleReviewedBody:
|
|
||||||
properties:
|
|
||||||
ids:
|
|
||||||
items:
|
|
||||||
type: string
|
|
||||||
minLength: 1
|
|
||||||
type: array
|
|
||||||
minItems: 1
|
|
||||||
title: Ids
|
|
||||||
type: object
|
|
||||||
required:
|
|
||||||
- ids
|
|
||||||
title: ReviewSetMultipleReviewedBody
|
|
||||||
ReviewSummaryResponse:
|
ReviewSummaryResponse:
|
||||||
properties:
|
properties:
|
||||||
last24Hours:
|
last24Hours:
|
||||||
|
0
frigate/api/defs/__init__.py
Normal file
0
frigate/api/defs/__init__.py
Normal file
0
frigate/api/defs/request/__init__.py
Normal file
0
frigate/api/defs/request/__init__.py
Normal file
20
frigate/api/defs/request/export_recordinds_body.py
Normal file
20
frigate/api/defs/request/export_recordinds_body.py
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
from typing import Union
|
||||||
|
|
||||||
|
from pydantic import BaseModel, Field
|
||||||
|
from pydantic.json_schema import SkipJsonSchema
|
||||||
|
|
||||||
|
from frigate.record.export import (
|
||||||
|
PlaybackFactorEnum,
|
||||||
|
PlaybackSourceEnum,
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class ExportRecordingsBody(BaseModel):
|
||||||
|
playback: PlaybackFactorEnum = Field(
|
||||||
|
default=PlaybackFactorEnum.realtime, title="Playback factor"
|
||||||
|
)
|
||||||
|
source: PlaybackSourceEnum = Field(
|
||||||
|
default=PlaybackSourceEnum.recordings, title="Playback source"
|
||||||
|
)
|
||||||
|
name: str = Field(title="Friendly name", default=None, max_length=256)
|
||||||
|
image_path: Union[str, SkipJsonSchema[None]] = None
|
@ -4,13 +4,13 @@ import logging
|
|||||||
import random
|
import random
|
||||||
import string
|
import string
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Optional
|
|
||||||
|
|
||||||
import psutil
|
import psutil
|
||||||
from fastapi import APIRouter, Request
|
from fastapi import APIRouter, Request
|
||||||
from fastapi.responses import JSONResponse
|
from fastapi.responses import JSONResponse
|
||||||
from peewee import DoesNotExist
|
from peewee import DoesNotExist
|
||||||
|
|
||||||
|
from frigate.api.defs.request.export_recordinds_body import ExportRecordingsBody
|
||||||
from frigate.api.defs.tags import Tags
|
from frigate.api.defs.tags import Tags
|
||||||
from frigate.const import EXPORT_DIR
|
from frigate.const import EXPORT_DIR
|
||||||
from frigate.models import Export, Previews, Recordings
|
from frigate.models import Export, Previews, Recordings
|
||||||
@ -37,7 +37,7 @@ def export_recording(
|
|||||||
camera_name: str,
|
camera_name: str,
|
||||||
start_time: float,
|
start_time: float,
|
||||||
end_time: float,
|
end_time: float,
|
||||||
body: dict = None,
|
body: ExportRecordingsBody,
|
||||||
):
|
):
|
||||||
if not camera_name or not request.app.frigate_config.cameras.get(camera_name):
|
if not camera_name or not request.app.frigate_config.cameras.get(camera_name):
|
||||||
return JSONResponse(
|
return JSONResponse(
|
||||||
@ -47,18 +47,10 @@ def export_recording(
|
|||||||
status_code=404,
|
status_code=404,
|
||||||
)
|
)
|
||||||
|
|
||||||
json: dict[str, any] = body or {}
|
playback_factor = body.playback
|
||||||
playback_factor = json.get("playback", "realtime")
|
playback_source = body.source
|
||||||
playback_source = json.get("source", "recordings")
|
friendly_name = body.name
|
||||||
friendly_name: Optional[str] = json.get("name")
|
existing_image = body.image_path
|
||||||
|
|
||||||
if len(friendly_name or "") > 256:
|
|
||||||
return JSONResponse(
|
|
||||||
content=({"success": False, "message": "File name is too long."}),
|
|
||||||
status_code=401,
|
|
||||||
)
|
|
||||||
|
|
||||||
existing_image = json.get("image_path")
|
|
||||||
|
|
||||||
if playback_source == "recordings":
|
if playback_source == "recordings":
|
||||||
recordings_count = (
|
recordings_count = (
|
||||||
|
Loading…
Reference in New Issue
Block a user