mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-03-10 02:29:19 +03:00
feat: add X-Frame-Time when returning snapshot (#21932)
Co-authored-by: Florent MORICONI <170678386+fmcloudconsulting@users.noreply.github.com>
This commit is contained in:
parent
2db0269825
commit
fef1fb36cc
@ -761,7 +761,7 @@ async def event_snapshot(
|
|||||||
if event_id in camera_state.tracked_objects:
|
if event_id in camera_state.tracked_objects:
|
||||||
tracked_obj = camera_state.tracked_objects.get(event_id)
|
tracked_obj = camera_state.tracked_objects.get(event_id)
|
||||||
if tracked_obj is not None:
|
if tracked_obj is not None:
|
||||||
jpg_bytes = tracked_obj.get_img_bytes(
|
jpg_bytes, frame_time = tracked_obj.get_img_bytes(
|
||||||
ext="jpg",
|
ext="jpg",
|
||||||
timestamp=params.timestamp,
|
timestamp=params.timestamp,
|
||||||
bounding_box=params.bbox,
|
bounding_box=params.bbox,
|
||||||
@ -790,6 +790,7 @@ async def event_snapshot(
|
|||||||
headers = {
|
headers = {
|
||||||
"Content-Type": "image/jpeg",
|
"Content-Type": "image/jpeg",
|
||||||
"Cache-Control": "private, max-age=31536000" if event_complete else "no-store",
|
"Cache-Control": "private, max-age=31536000" if event_complete else "no-store",
|
||||||
|
"X-Frame-Time": frame_time,
|
||||||
}
|
}
|
||||||
|
|
||||||
if params.download:
|
if params.download:
|
||||||
|
|||||||
@ -185,7 +185,7 @@ class TrackedObjectProcessor(threading.Thread):
|
|||||||
def snapshot(camera: str, obj: TrackedObject) -> bool:
|
def snapshot(camera: str, obj: TrackedObject) -> bool:
|
||||||
mqtt_config: CameraMqttConfig = self.config.cameras[camera].mqtt
|
mqtt_config: CameraMqttConfig = self.config.cameras[camera].mqtt
|
||||||
if mqtt_config.enabled and self.should_mqtt_snapshot(camera, obj):
|
if mqtt_config.enabled and self.should_mqtt_snapshot(camera, obj):
|
||||||
jpg_bytes = obj.get_img_bytes(
|
jpg_bytes, _ = obj.get_img_bytes(
|
||||||
ext="jpg",
|
ext="jpg",
|
||||||
timestamp=mqtt_config.timestamp,
|
timestamp=mqtt_config.timestamp,
|
||||||
bounding_box=mqtt_config.bounding_box,
|
bounding_box=mqtt_config.bounding_box,
|
||||||
|
|||||||
@ -434,7 +434,7 @@ class TrackedObject:
|
|||||||
return count > (self.camera_config.detect.stationary.threshold or 50)
|
return count > (self.camera_config.detect.stationary.threshold or 50)
|
||||||
|
|
||||||
def get_thumbnail(self, ext: str) -> bytes | None:
|
def get_thumbnail(self, ext: str) -> bytes | None:
|
||||||
img_bytes = self.get_img_bytes(
|
img_bytes, _ = self.get_img_bytes(
|
||||||
ext, timestamp=False, bounding_box=False, crop=True, height=175
|
ext, timestamp=False, bounding_box=False, crop=True, height=175
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -475,20 +475,21 @@ class TrackedObject:
|
|||||||
crop: bool = False,
|
crop: bool = False,
|
||||||
height: int | None = None,
|
height: int | None = None,
|
||||||
quality: int | None = None,
|
quality: int | None = None,
|
||||||
) -> bytes | None:
|
) -> tuple[bytes | None, float | None]:
|
||||||
if self.thumbnail_data is None:
|
if self.thumbnail_data is None:
|
||||||
return None
|
return None, None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
|
frame_time = self.thumbnail_data["frame_time"]
|
||||||
best_frame = cv2.cvtColor(
|
best_frame = cv2.cvtColor(
|
||||||
self.frame_cache[self.thumbnail_data["frame_time"]]["frame"],
|
self.frame_cache[frame_time]["frame"],
|
||||||
cv2.COLOR_YUV2BGR_I420,
|
cv2.COLOR_YUV2BGR_I420,
|
||||||
)
|
)
|
||||||
except KeyError:
|
except KeyError:
|
||||||
logger.warning(
|
logger.warning(
|
||||||
f"Unable to create jpg because frame {self.thumbnail_data['frame_time']} is not in the cache"
|
f"Unable to create jpg because frame {frame_time} is not in the cache"
|
||||||
)
|
)
|
||||||
return None
|
return None, None
|
||||||
|
|
||||||
if bounding_box:
|
if bounding_box:
|
||||||
thickness = 2
|
thickness = 2
|
||||||
@ -570,13 +571,13 @@ class TrackedObject:
|
|||||||
ret, jpg = cv2.imencode(f".{ext}", best_frame, quality_params)
|
ret, jpg = cv2.imencode(f".{ext}", best_frame, quality_params)
|
||||||
|
|
||||||
if ret:
|
if ret:
|
||||||
return jpg.tobytes()
|
return jpg.tobytes(), frame_time
|
||||||
else:
|
else:
|
||||||
return None
|
return None, None
|
||||||
|
|
||||||
def write_snapshot_to_disk(self) -> None:
|
def write_snapshot_to_disk(self) -> None:
|
||||||
snapshot_config: SnapshotsConfig = self.camera_config.snapshots
|
snapshot_config: SnapshotsConfig = self.camera_config.snapshots
|
||||||
jpg_bytes = self.get_img_bytes(
|
jpg_bytes, _ = self.get_img_bytes(
|
||||||
ext="jpg",
|
ext="jpg",
|
||||||
timestamp=snapshot_config.timestamp,
|
timestamp=snapshot_config.timestamp,
|
||||||
bounding_box=snapshot_config.bounding_box,
|
bounding_box=snapshot_config.bounding_box,
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user