Improve recording timeline and VOD query performance

This commit is contained in:
Fabien Del Olmo 2026-07-29 18:58:57 +02:00
parent 7ed7ed56cf
commit 1b0d2f8c54
3 changed files with 57 additions and 5 deletions

View File

@ -574,11 +574,11 @@ async def vod_ts(
Recordings.start_time,
)
.where(
Recordings.start_time.between(start_ts, end_ts)
| Recordings.end_time.between(start_ts, end_ts)
| ((start_ts > Recordings.start_time) & (end_ts < Recordings.end_time))
Recordings.camera == camera_name,
Recordings.start_time >= start_ts - MAX_SEGMENT_DURATION,
Recordings.start_time <= end_ts,
Recordings.end_time >= start_ts,
)
.where(Recordings.camera == camera_name)
.order_by(Recordings.start_time.asc())
.iterator()
)

View File

@ -25,7 +25,7 @@ from frigate.api.defs.query.recordings_query_parameters import (
)
from frigate.api.defs.response.generic_response import GenericResponse
from frigate.api.defs.tags import Tags
from frigate.const import RECORD_DIR
from frigate.const import MAX_SEGMENT_DURATION, RECORD_DIR
from frigate.models import Event, Recordings
from frigate.util.time import get_dst_transitions
@ -243,6 +243,7 @@ async def recordings(
)
.where(
Recordings.camera == camera_name,
Recordings.start_time >= after - MAX_SEGMENT_DURATION,
Recordings.end_time >= after,
Recordings.start_time <= before,
)

View File

@ -1,11 +1,13 @@
"""Unit tests for recordings/media API endpoints."""
from datetime import UTC, datetime
from unittest.mock import patch
import pytz
from fastapi import Request
from frigate.api.auth import get_allowed_cameras_for_filter, get_current_user
from frigate.const import MAX_SEGMENT_DURATION
from frigate.models import Recordings
from frigate.test.http_api.base_http_test import AuthTestClient, BaseTestHttp
@ -404,6 +406,55 @@ class TestHttpMedia(BaseTestHttp):
assert "2024-03-10" in summary
assert summary["2024-03-10"] is True
def test_recordings_returns_overlapping_segment(self):
"""Recordings include a segment that overlaps the requested range."""
after = 1000
before = 1100
with AuthTestClient(self.app) as client:
super().insert_mock_recording("too_old", after - 10, after - 1)
super().insert_mock_recording(
"overlap",
after - MAX_SEGMENT_DURATION + 1,
after,
)
super().insert_mock_recording("too_new", before + 1, before + 10)
response = client.get(
"/front_door/recordings",
params={"after": after, "before": before},
)
assert response.status_code == 200
assert [recording["id"] for recording in response.json()] == ["overlap"]
def test_vod_returns_overlapping_segment(self):
"""VOD mapping includes a segment that overlaps the requested range."""
start = 1000
end = 1100
with (
AuthTestClient(self.app) as client,
patch(
"frigate.api.media.get_keyframe_before",
return_value=None,
),
):
super().insert_mock_recording("too_old", start - 10, start - 1)
super().insert_mock_recording(
"overlap",
start - MAX_SEGMENT_DURATION + 2,
start + 1,
)
super().insert_mock_recording("too_new", end + 1, end + 10)
response = client.get(f"/vod/front_door/start/{start}/end/{end}")
assert response.status_code == 200
assert [
clip["path"] for clip in response.json()["sequences"][0]["clips"]
] == ["overlap"]
def test_recordings_unavailable_reports_gap_between_recordings(self):
"""A gap between two recordings is reported as an unavailable segment."""
with AuthTestClient(self.app) as client: