mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-06-20 19:31:53 +03:00
Chapter tweaks (#23440)
Some checks failed
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
Some checks failed
CI / AMD64 Build (push) Has been cancelled
CI / ARM Build (push) Has been cancelled
CI / Jetson Jetpack 6 (push) Has been cancelled
CI / AMD64 Extra Build (push) Has been cancelled
CI / ARM Extra Build (push) Has been cancelled
CI / Synaptics Build (push) Has been cancelled
CI / Assemble and push default build (push) Has been cancelled
* Add camera metadata and fix preview chapters * Add config option for chapters
This commit is contained in:
parent
28e3e1ec74
commit
06e3d0ac5d
@ -31,7 +31,6 @@ from frigate.api.defs.tags import Tags
|
||||
from frigate.const import CLIPS_DIR, EXPORT_DIR
|
||||
from frigate.models import Export, Previews, Recordings
|
||||
from frigate.record.export import (
|
||||
ChaptersEnum,
|
||||
PlaybackFactorEnum,
|
||||
PlaybackSourceEnum,
|
||||
RecordingExporter,
|
||||
@ -94,6 +93,14 @@ def export_recording(
|
||||
friendly_name = body.name
|
||||
existing_image = sanitize_filepath(body.image_path) if body.image_path else None
|
||||
|
||||
# a chapters value in the request body overrides the camera's export config
|
||||
camera_config = request.app.frigate_config.cameras[camera_name]
|
||||
chapters = (
|
||||
body.chapters
|
||||
if body.chapters is not None
|
||||
else camera_config.record.export.chapters
|
||||
)
|
||||
|
||||
# Ensure that existing_image is a valid path
|
||||
if existing_image and not existing_image.startswith(CLIPS_DIR):
|
||||
return JSONResponse(
|
||||
@ -162,7 +169,7 @@ def export_recording(
|
||||
if playback_source in PlaybackSourceEnum.__members__.values()
|
||||
else PlaybackSourceEnum.recordings
|
||||
),
|
||||
chapters=ChaptersEnum(body.chapters) if body.chapters else None,
|
||||
chapters=chapters,
|
||||
)
|
||||
exporter.start()
|
||||
return JSONResponse(
|
||||
|
||||
@ -9,6 +9,7 @@ from frigate.review.types import SeverityEnum
|
||||
from ..base import FrigateBaseModel
|
||||
|
||||
__all__ = [
|
||||
"ChaptersEnum",
|
||||
"RecordConfig",
|
||||
"RecordExportConfig",
|
||||
"RecordPreviewConfig",
|
||||
@ -66,10 +67,19 @@ class RecordPreviewConfig(FrigateBaseModel):
|
||||
)
|
||||
|
||||
|
||||
class ChaptersEnum(str, Enum):
|
||||
none = "none"
|
||||
recording_segments = "recording_segments"
|
||||
|
||||
|
||||
class RecordExportConfig(FrigateBaseModel):
|
||||
timelapse_args: str = Field(
|
||||
default=DEFAULT_TIME_LAPSE_FFMPEG_ARGS, title="Timelapse Args"
|
||||
)
|
||||
chapters: ChaptersEnum = Field(
|
||||
default=ChaptersEnum.none,
|
||||
title="Chapter metadata to embed in exported recordings",
|
||||
)
|
||||
|
||||
|
||||
class RecordConfig(FrigateBaseModel):
|
||||
|
||||
@ -16,6 +16,7 @@ import pytz
|
||||
from peewee import DoesNotExist
|
||||
|
||||
from frigate.config import FfmpegConfig, FrigateConfig
|
||||
from frigate.config.camera.record import ChaptersEnum
|
||||
from frigate.const import (
|
||||
CACHE_DIR,
|
||||
CLIPS_DIR,
|
||||
@ -51,14 +52,6 @@ class PlaybackSourceEnum(str, Enum):
|
||||
preview = "preview"
|
||||
|
||||
|
||||
class ChaptersEnum(str, Enum):
|
||||
# One chapter per recording segment, titled with the segment's
|
||||
# wallclock start time in strict ISO 8601 form. Lets viewers map
|
||||
# output playback time back to wallclock without reading a timestamp
|
||||
# overlay via OCR.
|
||||
recording_segments = "recording_segments"
|
||||
|
||||
|
||||
class RecordingExporter(threading.Thread):
|
||||
"""Exports a specific set of recordings for a camera to storage as a single file."""
|
||||
|
||||
@ -358,6 +351,8 @@ class RecordingExporter(threading.Thread):
|
||||
f"title={title}",
|
||||
"-metadata",
|
||||
f"creation_time={creation_time}",
|
||||
"-metadata",
|
||||
f"comment=Camera: {self.camera}",
|
||||
]
|
||||
)
|
||||
|
||||
@ -435,7 +430,7 @@ class RecordingExporter(threading.Thread):
|
||||
|
||||
if self.playback_factor == PlaybackFactorEnum.realtime:
|
||||
ffmpeg_cmd = (
|
||||
f"{self.config.ffmpeg.ffmpeg_path} -hide_banner {ffmpeg_input} {codec} -movflags +faststart {video_path}"
|
||||
f"{self.config.ffmpeg.ffmpeg_path} -hide_banner {ffmpeg_input} {codec} -movflags +faststart"
|
||||
).split(" ")
|
||||
elif self.playback_factor == PlaybackFactorEnum.timelapse_25x:
|
||||
ffmpeg_cmd = (
|
||||
@ -443,7 +438,7 @@ class RecordingExporter(threading.Thread):
|
||||
self.config.ffmpeg.ffmpeg_path,
|
||||
self.config.ffmpeg.hwaccel_args,
|
||||
f"{TIMELAPSE_DATA_INPUT_ARGS} {ffmpeg_input}",
|
||||
f"{self.config.cameras[self.camera].record.export.timelapse_args} -movflags +faststart {video_path}",
|
||||
f"{self.config.cameras[self.camera].record.export.timelapse_args} -movflags +faststart",
|
||||
EncodeTypeEnum.timelapse,
|
||||
)
|
||||
).split(" ")
|
||||
@ -459,9 +454,13 @@ class RecordingExporter(threading.Thread):
|
||||
f"title={title}",
|
||||
"-metadata",
|
||||
f"creation_time={creation_time}",
|
||||
"-metadata",
|
||||
f"comment=Camera: {self.camera}",
|
||||
]
|
||||
)
|
||||
|
||||
ffmpeg_cmd.append(video_path)
|
||||
|
||||
return ffmpeg_cmd, playlist_lines
|
||||
|
||||
def run(self) -> None:
|
||||
|
||||
Loading…
Reference in New Issue
Block a user