mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-09-24 18:26:51 +03:00
Miscellaneous fixes (#24179)
* rename migration * use ASC composite index for event camera and start_time the planner still picks for newest-first single-camera queries but doesn't slow down full per-camera scans on a cold cache * pause playback while the timeline range handles are up * reduce multi camera seeded export range to 30m allows both handlebars to fit within most desktop windows
This commit is contained in:
committed by
Nicolas Mowen
parent
11b4d34f93
commit
d6b93301e2
@@ -1,6 +1,6 @@
|
|||||||
"""Peewee migrations -- 036_add_perf_indexes.py.
|
"""Peewee migrations -- 039_add_perf_indexes.py.
|
||||||
|
|
||||||
Adds composite/single-column indexes to speed up single-camera queries
|
Adds a composite (camera, start_time) index to speed up single-camera queries
|
||||||
issued by the web UI.
|
issued by the web UI.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
@@ -13,7 +13,7 @@ SQL = pw.SQL
|
|||||||
def migrate(migrator, database, fake=False, **kwargs):
|
def migrate(migrator, database, fake=False, **kwargs):
|
||||||
migrator.sql(
|
migrator.sql(
|
||||||
'CREATE INDEX IF NOT EXISTS "event_camera_start_time" '
|
'CREATE INDEX IF NOT EXISTS "event_camera_start_time" '
|
||||||
'ON "event" ("camera", "start_time" DESC)'
|
'ON "event" ("camera", "start_time")'
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -80,7 +80,7 @@ type ExportOption = (typeof EXPORT_OPTIONS)[number];
|
|||||||
export type ExportTab = "export" | "multi";
|
export type ExportTab = "export" | "multi";
|
||||||
|
|
||||||
// length of a range seeded around the current playback time
|
// length of a range seeded around the current playback time
|
||||||
const MULTI_CAMERA_RANGE_SECONDS = 3600;
|
const MULTI_CAMERA_RANGE_SECONDS = 1800;
|
||||||
const TIMELINE_SELECTION_SECONDS = 60;
|
const TIMELINE_SELECTION_SECONDS = 60;
|
||||||
|
|
||||||
type ExportDialogProps = {
|
type ExportDialogProps = {
|
||||||
|
|||||||
@@ -231,6 +231,14 @@ export function RecordingView({
|
|||||||
|
|
||||||
const [debugReplayMode, setDebugReplayMode] = useState<ExportMode>("none");
|
const [debugReplayMode, setDebugReplayMode] = useState<ExportMode>("none");
|
||||||
const [debugReplayRange, setDebugReplayRange] = useState<TimeRange>();
|
const [debugReplayRange, setDebugReplayRange] = useState<TimeRange>();
|
||||||
|
|
||||||
|
// while the range handles are up the player has to stay put: the
|
||||||
|
// timeline auto-scrolls to follow the playhead once the interaction
|
||||||
|
// timeout lapses, yanking the view out from under the drag
|
||||||
|
const selectingRange =
|
||||||
|
exportMode == "timeline" ||
|
||||||
|
exportMode == "timeline_multi" ||
|
||||||
|
debugReplayMode == "timeline";
|
||||||
const [shareTimestampOpen, setShareTimestampOpen] = useState(false);
|
const [shareTimestampOpen, setShareTimestampOpen] = useState(false);
|
||||||
const [shareTimestampAtOpen, setShareTimestampAtOpen] = useState(
|
const [shareTimestampAtOpen, setShareTimestampAtOpen] = useState(
|
||||||
Math.floor(startTime),
|
Math.floor(startTime),
|
||||||
@@ -338,6 +346,19 @@ export function RecordingView({
|
|||||||
updateSelectedSegment,
|
updateSelectedSegment,
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
const wasPlayingBeforeSelectRef = useRef(false);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
|
if (selectingRange) {
|
||||||
|
wasPlayingBeforeSelectRef.current =
|
||||||
|
mainControllerRef.current?.isPlaying() ?? false;
|
||||||
|
mainControllerRef.current?.pause();
|
||||||
|
} else if (wasPlayingBeforeSelectRef.current) {
|
||||||
|
wasPlayingBeforeSelectRef.current = false;
|
||||||
|
mainControllerRef.current?.play();
|
||||||
|
}
|
||||||
|
}, [selectingRange]);
|
||||||
|
|
||||||
const manuallySetCurrentTime = useCallback(
|
const manuallySetCurrentTime = useCallback(
|
||||||
(time: number, play: boolean = false) => {
|
(time: number, play: boolean = false) => {
|
||||||
if (!currentTimeRange) {
|
if (!currentTimeRange) {
|
||||||
@@ -396,7 +417,7 @@ export function RecordingView({
|
|||||||
}, [navigate, recording?.navigationSource]);
|
}, [navigate, recording?.navigationSource]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!scrubbing) {
|
if (!scrubbing && !selectingRange) {
|
||||||
if (Math.abs(currentTime - playerTime) > 10) {
|
if (Math.abs(currentTime - playerTime) > 10) {
|
||||||
if (
|
if (
|
||||||
currentTimeRange.after <= currentTime &&
|
currentTimeRange.after <= currentTime &&
|
||||||
@@ -423,9 +444,10 @@ export function RecordingView({
|
|||||||
mainControllerRef.current?.play();
|
mainControllerRef.current?.play();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// we only want to seek when current time doesn't match the player update time
|
// we only want to seek when current time doesn't match the player update
|
||||||
|
// time, and once more on the way out of a range selection
|
||||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||||
}, [currentTime, scrubbing]);
|
}, [currentTime, scrubbing, selectingRange]);
|
||||||
|
|
||||||
const [fullResolution, setFullResolution] = useState<VideoResolutionType>({
|
const [fullResolution, setFullResolution] = useState<VideoResolutionType>({
|
||||||
width: 0,
|
width: 0,
|
||||||
@@ -737,13 +759,7 @@ export function RecordingView({
|
|||||||
latestTime={timeRange.before}
|
latestTime={timeRange.before}
|
||||||
mode={debugReplayMode}
|
mode={debugReplayMode}
|
||||||
range={debugReplayRange}
|
range={debugReplayRange}
|
||||||
setRange={(range: TimeRange | undefined) => {
|
setRange={setDebugReplayRange}
|
||||||
setDebugReplayRange(range);
|
|
||||||
|
|
||||||
if (range != undefined) {
|
|
||||||
mainControllerRef.current?.pause();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
setMode={setDebugReplayMode}
|
setMode={setDebugReplayMode}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
@@ -756,13 +772,7 @@ export function RecordingView({
|
|||||||
mode={exportMode}
|
mode={exportMode}
|
||||||
range={exportRange}
|
range={exportRange}
|
||||||
showPreview={showExportPreview}
|
showPreview={showExportPreview}
|
||||||
setRange={(range) => {
|
setRange={setExportRange}
|
||||||
setExportRange(range);
|
|
||||||
|
|
||||||
if (range != undefined) {
|
|
||||||
mainControllerRef.current?.pause();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
setMode={setExportMode}
|
setMode={setExportMode}
|
||||||
setShowPreview={setShowExportPreview}
|
setShowPreview={setShowExportPreview}
|
||||||
/>
|
/>
|
||||||
@@ -925,13 +935,7 @@ export function RecordingView({
|
|||||||
debugReplayMode={debugReplayMode}
|
debugReplayMode={debugReplayMode}
|
||||||
debugReplayRange={debugReplayRange}
|
debugReplayRange={debugReplayRange}
|
||||||
setDebugReplayMode={setDebugReplayMode}
|
setDebugReplayMode={setDebugReplayMode}
|
||||||
setDebugReplayRange={(range: TimeRange | undefined) => {
|
setDebugReplayRange={setDebugReplayRange}
|
||||||
setDebugReplayRange(range);
|
|
||||||
|
|
||||||
if (range != undefined) {
|
|
||||||
mainControllerRef.current?.pause();
|
|
||||||
}
|
|
||||||
}}
|
|
||||||
onShareTimestamp={onShareReviewLink}
|
onShareTimestamp={onShareReviewLink}
|
||||||
onMotionSearch={
|
onMotionSearch={
|
||||||
onMotionSearch ? () => onMotionSearch(mainCamera) : undefined
|
onMotionSearch ? () => onMotionSearch(mainCamera) : undefined
|
||||||
|
|||||||
Reference in New Issue
Block a user