blakeblackshear.frigate/frigate/models.py
Josh Hawkins 57bb0cc397
Semantic Search Triggers (#18969)
* semantic trigger test

* database and model

* config

* embeddings maintainer and trigger post-processor

* api to create, edit, delete triggers

* frontend and i18n keys

* use thumbnail and description for trigger types

* image picker tweaks

* initial sync

* thumbnail file management

* clean up logs and use saved thumbnail on frontend

* publish mqtt messages

* webpush changes to enable trigger notifications

* add enabled switch

* add triggers from explore

* renaming and deletion fixes

* fix typing

* UI updates and add last triggering event time and link

* log exception instead of return in endpoint

* highlight entry in UI when triggered

* save and delete thumbnails directly

* remove alert action for now and add descriptions

* tweaks

* clean up

* fix types

* docs

* docs tweaks

* docs

* reuse enum
2025-07-07 09:03:57 -05:00

152 lines
5.0 KiB
Python

from peewee import (
BlobField,
BooleanField,
CharField,
CompositeKey,
DateTimeField,
FloatField,
ForeignKeyField,
IntegerField,
Model,
TextField,
)
from playhouse.sqlite_ext import JSONField
class Event(Model): # type: ignore[misc]
id = CharField(null=False, primary_key=True, max_length=30)
label = CharField(index=True, max_length=20)
sub_label = CharField(max_length=100, null=True)
camera = CharField(index=True, max_length=20)
start_time = DateTimeField()
end_time = DateTimeField()
top_score = (
FloatField()
) # TODO remove when columns can be dropped without rebuilding table
score = (
FloatField()
) # TODO remove when columns can be dropped without rebuilding table
false_positive = BooleanField()
zones = JSONField()
thumbnail = TextField()
has_clip = BooleanField(default=True)
has_snapshot = BooleanField(default=True)
region = (
JSONField()
) # TODO remove when columns can be dropped without rebuilding table
box = (
JSONField()
) # TODO remove when columns can be dropped without rebuilding table
area = (
IntegerField()
) # TODO remove when columns can be dropped without rebuilding table
retain_indefinitely = BooleanField(default=False)
ratio = FloatField(
default=1.0
) # TODO remove when columns can be dropped without rebuilding table
plus_id = CharField(max_length=30)
model_hash = CharField(max_length=32)
detector_type = CharField(max_length=32)
model_type = CharField(max_length=32)
data = JSONField() # ex: tracked object box, region, etc.
class Timeline(Model): # type: ignore[misc]
timestamp = DateTimeField()
camera = CharField(index=True, max_length=20)
source = CharField(index=True, max_length=20) # ex: tracked object, audio, external
source_id = CharField(index=True, max_length=30)
class_type = CharField(max_length=50) # ex: entered_zone, audio_heard
data = JSONField() # ex: tracked object id, region, box, etc.
class Regions(Model): # type: ignore[misc]
camera = CharField(null=False, primary_key=True, max_length=20)
grid = JSONField() # json blob of grid
last_update = DateTimeField()
class Recordings(Model): # type: ignore[misc]
id = CharField(null=False, primary_key=True, max_length=30)
camera = CharField(index=True, max_length=20)
path = CharField(unique=True)
start_time = DateTimeField()
end_time = DateTimeField()
duration = FloatField()
motion = IntegerField(null=True)
objects = IntegerField(null=True)
dBFS = IntegerField(null=True)
segment_size = FloatField(default=0) # this should be stored as MB
regions = IntegerField(null=True)
class Export(Model): # type: ignore[misc]
id = CharField(null=False, primary_key=True, max_length=30)
camera = CharField(index=True, max_length=20)
name = CharField(index=True, max_length=100)
date = DateTimeField()
video_path = CharField(unique=True)
thumb_path = CharField(unique=True)
in_progress = BooleanField()
class ReviewSegment(Model): # type: ignore[misc]
id = CharField(null=False, primary_key=True, max_length=30)
camera = CharField(index=True, max_length=20)
start_time = DateTimeField()
end_time = DateTimeField()
severity = CharField(max_length=30) # alert, detection
thumb_path = CharField(unique=True)
data = JSONField() # additional data about detection like list of labels, zone, areas of significant motion
class UserReviewStatus(Model): # type: ignore[misc]
user_id = CharField(max_length=30)
review_segment = ForeignKeyField(ReviewSegment, backref="user_reviews")
has_been_reviewed = BooleanField(default=False)
class Meta:
indexes = ((("user_id", "review_segment"), True),)
class Previews(Model): # type: ignore[misc]
id = CharField(null=False, primary_key=True, max_length=30)
camera = CharField(index=True, max_length=20)
path = CharField(unique=True)
start_time = DateTimeField()
end_time = DateTimeField()
duration = FloatField()
# Used for temporary table in record/cleanup.py
class RecordingsToDelete(Model): # type: ignore[misc]
id = CharField(null=False, primary_key=False, max_length=30)
class Meta:
temporary = True
class User(Model): # type: ignore[misc]
username = CharField(null=False, primary_key=True, max_length=30)
role = CharField(
max_length=20,
default="admin",
)
password_hash = CharField(null=False, max_length=120)
notification_tokens = JSONField()
class Trigger(Model): # type: ignore[misc]
camera = CharField(max_length=20)
name = CharField()
type = CharField(max_length=10)
data = TextField()
threshold = FloatField()
model = CharField(max_length=30)
embedding = BlobField()
triggering_event_id = CharField(max_length=30)
last_triggered = DateTimeField()
class Meta:
primary_key = CompositeKey("camera", "name")