mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-02-05 10:45:21 +03:00
Add option to archive expired records to S3 instead of deleting them
This commit is contained in:
parent
f60af0f212
commit
07cdec0718
@ -523,6 +523,7 @@ class SnapshotsConfig(FrigateBaseModel):
|
|||||||
|
|
||||||
class StorageS3Config(FrigateBaseModel):
|
class StorageS3Config(FrigateBaseModel):
|
||||||
enabled: bool = Field(default=False, title="S3 enabled.")
|
enabled: bool = Field(default=False, title="S3 enabled.")
|
||||||
|
archive: bool = Field(default=False, title="Archive expired records to S3 instead of delete")
|
||||||
access_key_id: str = Field(default="", title="AWS_ACCESS_KEY_ID")
|
access_key_id: str = Field(default="", title="AWS_ACCESS_KEY_ID")
|
||||||
secret_access_key: str = Field(default="", title="AWS_SECRET_ACCESS_KEY")
|
secret_access_key: str = Field(default="", title="AWS_SECRET_ACCESS_KEY")
|
||||||
bucket_name: str = Field(default="", title="Bucket name")
|
bucket_name: str = Field(default="", title="Bucket name")
|
||||||
|
|||||||
@ -29,7 +29,7 @@ class RecordingCleanup(threading.Thread):
|
|||||||
self.config = config
|
self.config = config
|
||||||
self.stop_event = stop_event
|
self.stop_event = stop_event
|
||||||
|
|
||||||
if self.config.storage.s3.enabled:
|
if self.config.storage.s3.enabled or self.config.storage.s3.archive:
|
||||||
self.s3 = StorageS3(config)
|
self.s3 = StorageS3(config)
|
||||||
|
|
||||||
def clean_tmp_clips(self) -> None:
|
def clean_tmp_clips(self) -> None:
|
||||||
@ -144,7 +144,7 @@ class RecordingCleanup(threading.Thread):
|
|||||||
and recording.objects == 0
|
and recording.objects == 0
|
||||||
)
|
)
|
||||||
):
|
):
|
||||||
if self.config.storage.s3.enabled:
|
if self.config.storage.s3.archive:
|
||||||
s3path = self.s3.upload_file_to_s3(recording.path)
|
s3path = self.s3.upload_file_to_s3(recording.path)
|
||||||
if s3path != "":
|
if s3path != "":
|
||||||
moved_recordings.add({"id": recording.id, "path": s3path})
|
moved_recordings.add({"id": recording.id, "path": s3path})
|
||||||
|
|||||||
@ -21,6 +21,7 @@ from frigate.const import CACHE_DIR, MAX_SEGMENT_DURATION, RECORD_DIR
|
|||||||
from frigate.models import Event, Recordings
|
from frigate.models import Event, Recordings
|
||||||
from frigate.types import RecordMetricsTypes
|
from frigate.types import RecordMetricsTypes
|
||||||
from frigate.util import area
|
from frigate.util import area
|
||||||
|
from frigate.storage import StorageS3
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
@ -42,6 +43,9 @@ class RecordingMaintainer(threading.Thread):
|
|||||||
self.recordings_info: dict[str, Any] = defaultdict(list)
|
self.recordings_info: dict[str, Any] = defaultdict(list)
|
||||||
self.end_time_cache: dict[str, Tuple[datetime.datetime, float]] = {}
|
self.end_time_cache: dict[str, Tuple[datetime.datetime, float]] = {}
|
||||||
|
|
||||||
|
if self.config.storage.s3.enabled:
|
||||||
|
self.s3 = StorageS3(config)
|
||||||
|
|
||||||
def move_files(self) -> None:
|
def move_files(self) -> None:
|
||||||
cache_files = sorted(
|
cache_files = sorted(
|
||||||
[
|
[
|
||||||
@ -335,6 +339,17 @@ class RecordingMaintainer(threading.Thread):
|
|||||||
rand_id = "".join(
|
rand_id = "".join(
|
||||||
random.choices(string.ascii_lowercase + string.digits, k=6)
|
random.choices(string.ascii_lowercase + string.digits, k=6)
|
||||||
)
|
)
|
||||||
|
storage = "local"
|
||||||
|
if self.config.storage.s3.enabled:
|
||||||
|
s3path = self.s3.upload_file_to_s3(file_path)
|
||||||
|
if s3path != "":
|
||||||
|
Path(file_path).unlink(missing_ok=True)
|
||||||
|
file_path = s3path
|
||||||
|
storage = "s3"
|
||||||
|
else:
|
||||||
|
logger.error(f"Unable to upload recording segment {file_path} to s3, fallback to local")
|
||||||
|
logger.error(e)
|
||||||
|
|
||||||
Recordings.create(
|
Recordings.create(
|
||||||
id=f"{start_time.timestamp()}-{rand_id}",
|
id=f"{start_time.timestamp()}-{rand_id}",
|
||||||
camera=camera,
|
camera=camera,
|
||||||
@ -346,6 +361,7 @@ class RecordingMaintainer(threading.Thread):
|
|||||||
# TODO: update this to store list of active objects at some point
|
# TODO: update this to store list of active objects at some point
|
||||||
objects=active_count,
|
objects=active_count,
|
||||||
segment_size=segment_size,
|
segment_size=segment_size,
|
||||||
|
storage=storage,
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Unable to store recording segment {cache_path}")
|
logger.error(f"Unable to store recording segment {cache_path}")
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user