diff --git a/web/src/components/overlay/detail/SearchDetailDialog.tsx b/web/src/components/overlay/detail/SearchDetailDialog.tsx
index 28ef5c45b..02957a8de 100644
--- a/web/src/components/overlay/detail/SearchDetailDialog.tsx
+++ b/web/src/components/overlay/detail/SearchDetailDialog.tsx
@@ -77,6 +77,7 @@ import { Trans, useTranslation } from "react-i18next";
import { TbFaceId } from "react-icons/tb";
import { useIsAdmin } from "@/hooks/use-is-admin";
import FaceSelectionDialog from "../FaceSelectionDialog";
+import { CgTranscript } from "react-icons/cg";
const SEARCH_TABS = [
"details",
@@ -709,6 +710,34 @@ function ObjectDetailsTab({
[search, t],
);
+ // speech transcription
+
+ const onTranscribe = useCallback(() => {
+ axios
+ .put(`/audio/transcribe`, { event_id: search.id })
+ .then((resp) => {
+ if (resp.status == 202) {
+ toast.success(t("details.item.toast.success.audioTranscription"), {
+ position: "top-center",
+ });
+ }
+ })
+ .catch((error) => {
+ const errorMessage =
+ error.response?.data?.message ||
+ error.response?.data?.detail ||
+ "Unknown error";
+ toast.error(
+ t("details.item.toast.error.audioTranscription", {
+ errorMessage,
+ }),
+ {
+ position: "top-center",
+ },
+ );
+ });
+ }, [search, t]);
+
return (
@@ -894,6 +923,16 @@ function ObjectDetailsTab({
)}
+ {config?.cameras[search?.camera].audio_transcription.enabled &&
+ search?.label == "speech" &&
+ search?.end_time && (
+
+ )}
diff --git a/web/src/pages/Explore.tsx b/web/src/pages/Explore.tsx
index 7e412201e..a911819b2 100644
--- a/web/src/pages/Explore.tsx
+++ b/web/src/pages/Explore.tsx
@@ -246,15 +246,13 @@ export default function Explore() {
// mutation and revalidation
- const trackedObjectUpdate = useTrackedObjectUpdate();
+ const { payload: wsUpdate } = useTrackedObjectUpdate();
useEffect(() => {
- if (trackedObjectUpdate) {
+ if (wsUpdate && wsUpdate.type == "description") {
mutate();
}
- // mutate / revalidate when event description updates come in
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [trackedObjectUpdate]);
+ }, [wsUpdate, mutate]);
// embeddings reindex progress
diff --git a/web/src/views/explore/ExploreView.tsx b/web/src/views/explore/ExploreView.tsx
index afe5001af..f5cdb220d 100644
--- a/web/src/views/explore/ExploreView.tsx
+++ b/web/src/views/explore/ExploreView.tsx
@@ -74,13 +74,13 @@ export default function ExploreView({
}, {});
}, [events]);
- const trackedObjectUpdate = useTrackedObjectUpdate();
+ const { payload: wsUpdate } = useTrackedObjectUpdate();
useEffect(() => {
- mutate();
- // mutate / revalidate when event description updates come in
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [trackedObjectUpdate]);
+ if (wsUpdate && wsUpdate.type == "description") {
+ mutate();
+ }
+ }, [wsUpdate, mutate]);
// update search detail when results change