diff --git a/frigate/embeddings/embeddings.py b/frigate/embeddings/embeddings.py index 85c65b33e..4883e0914 100644 --- a/frigate/embeddings/embeddings.py +++ b/frigate/embeddings/embeddings.py @@ -175,6 +175,7 @@ class Embeddings: "descriptions": 0, "processed_objects": 0, "total_objects": 0, + "time_remaining": 0, } self.requestor.send_data(UPDATE_EMBEDDINGS_REINDEX_PROGRESS, totals) @@ -229,6 +230,13 @@ class Embeddings: totals["descriptions"], ) + # Calculate time remaining + elapsed_time = time.time() - st + avg_time_per_event = elapsed_time / totals["processed_objects"] + remaining_events = total_events - totals["processed_objects"] + time_remaining = avg_time_per_event * remaining_events + totals["time_remaining"] = int(time_remaining) + self.requestor.send_data(UPDATE_EMBEDDINGS_REINDEX_PROGRESS, totals) # Move to the next page diff --git a/web/src/pages/Explore.tsx b/web/src/pages/Explore.tsx index 59c3fd895..a3d7d3085 100644 --- a/web/src/pages/Explore.tsx +++ b/web/src/pages/Explore.tsx @@ -10,6 +10,7 @@ import { useTimezone } from "@/hooks/use-date-utils"; import { FrigateConfig } from "@/types/frigateConfig"; import { SearchFilter, SearchQuery, SearchResult } from "@/types/search"; import { ModelState } from "@/types/ws"; +import { formatSecondsToDuration } from "@/utils/dateUtil"; import SearchView from "@/views/search/SearchView"; import { useCallback, useEffect, useMemo, useState } from "react"; import { LuCheck, LuExternalLink, LuX } from "react-icons/lu"; @@ -282,6 +283,16 @@ export default function Explore() { />
+ {reindexProgress.time_remaining >= 0 && ( +
+
+ Estimated time remaining: +
+ {formatSecondsToDuration( + reindexProgress.time_remaining, + ) || "Finishing shortly"} +
+ )}
Thumbnails embedded: diff --git a/web/src/types/ws.ts b/web/src/types/ws.ts index cab759074..238ef4a8a 100644 --- a/web/src/types/ws.ts +++ b/web/src/types/ws.ts @@ -67,6 +67,7 @@ export type EmbeddingsReindexProgressType = { descriptions: number; processed_objects: number; total_objects: number; + time_remaining: number; }; export type ToggleableSetting = "ON" | "OFF"; diff --git a/web/src/utils/dateUtil.ts b/web/src/utils/dateUtil.ts index dc5589884..8509155e1 100644 --- a/web/src/utils/dateUtil.ts +++ b/web/src/utils/dateUtil.ts @@ -229,6 +229,23 @@ export const getDurationFromTimestamps = ( return duration; }; +/** + * + * @param seconds - number of seconds to convert into hours, minutes and seconds + * @returns string - formatted duration in hours, minutes and seconds + */ +export const formatSecondsToDuration = (seconds: number): string => { + if (isNaN(seconds) || seconds < 0) { + return "Invalid duration"; + } + + const duration = intervalToDuration({ start: 0, end: seconds * 1000 }); + return formatDuration(duration, { + format: ["hours", "minutes", "seconds"], + delimiter: ", ", + }); +}; + /** * Adapted from https://stackoverflow.com/a/29268535 this takes a timezone string and * returns the offset of that timezone from UTC in minutes.