Compare commits

...

4 Commits

Author SHA1 Message Date
Chris
d15886e691
Merge 793906bb68 into b0527df3c7 2025-11-21 01:48:22 +02:00
Nicolas Mowen
b0527df3c7
HLS adjustments (#20983)
* Revert "Fix HLS jumping to end of timeChunk (#20982)"

This reverts commit 301e0a1a3a.

* Never use native HLS

* Fix inverse operation
2025-11-20 15:58:58 -07:00
Nicolas Mowen
301e0a1a3a
Fix HLS jumping to end of timeChunk (#20982)
* Fix HLS jumping to end

* Undo
2025-11-20 15:50:00 -06:00
Chris Suich
793906bb68 feat: use persisted state for selected camera on settings page
Leverage the usePersistence() hook to store the selected camera so that
navigating away from the settings page and back will remember the
selected camera.
2025-11-15 11:26:59 -05:00
3 changed files with 19 additions and 4 deletions

View File

@ -6,7 +6,7 @@ import {
useState, useState,
} from "react"; } from "react";
import Hls from "hls.js"; import Hls from "hls.js";
import { isAndroid, isDesktop, isMobile } from "react-device-detect"; import { isDesktop, isMobile } from "react-device-detect";
import { TransformComponent, TransformWrapper } from "react-zoom-pan-pinch"; import { TransformComponent, TransformWrapper } from "react-zoom-pan-pinch";
import VideoControls from "./VideoControls"; import VideoControls from "./VideoControls";
import { VideoResolutionType } from "@/types/live"; import { VideoResolutionType } from "@/types/live";
@ -22,7 +22,7 @@ import { useTranslation } from "react-i18next";
import ObjectTrackOverlay from "@/components/overlay/ObjectTrackOverlay"; import ObjectTrackOverlay from "@/components/overlay/ObjectTrackOverlay";
// Android native hls does not seek correctly // Android native hls does not seek correctly
const USE_NATIVE_HLS = !isAndroid; const USE_NATIVE_HLS = false;
const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const; const HLS_MIME_TYPE = "application/vnd.apple.mpegurl" as const;
const unsupportedErrorCodes = [ const unsupportedErrorCodes = [
MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED, MediaError.MEDIA_ERR_SRC_NOT_SUPPORTED,

View File

@ -111,7 +111,7 @@ export default function DynamicVideoPlayer({
const [loadingTimeout, setLoadingTimeout] = useState<NodeJS.Timeout>(); const [loadingTimeout, setLoadingTimeout] = useState<NodeJS.Timeout>();
const [source, setSource] = useState<HlsSource>({ const [source, setSource] = useState<HlsSource>({
playlist: `${apiHost}vod/${camera}/start/${timeRange.after}/end/${timeRange.before}/master.m3u8`, playlist: `${apiHost}vod/${camera}/start/${timeRange.after}/end/${timeRange.before}/master.m3u8`,
startPosition: startTimestamp ? timeRange.after - startTimestamp : 0, startPosition: startTimestamp ? startTimestamp - timeRange.after : 0,
}); });
// start at correct time // start at correct time

View File

@ -37,6 +37,7 @@ import EnrichmentsSettingsView from "@/views/settings/EnrichmentsSettingsView";
import UiSettingsView from "@/views/settings/UiSettingsView"; import UiSettingsView from "@/views/settings/UiSettingsView";
import FrigatePlusSettingsView from "@/views/settings/FrigatePlusSettingsView"; import FrigatePlusSettingsView from "@/views/settings/FrigatePlusSettingsView";
import { useSearchEffect } from "@/hooks/use-overlay-state"; import { useSearchEffect } from "@/hooks/use-overlay-state";
import { usePersistence } from "@/hooks/use-persistence";
import { useNavigate, useSearchParams } from "react-router-dom"; import { useNavigate, useSearchParams } from "react-router-dom";
import { useInitialCameraState } from "@/api/ws"; import { useInitialCameraState } from "@/api/ws";
import { useIsAdmin } from "@/hooks/use-is-admin"; import { useIsAdmin } from "@/hooks/use-is-admin";
@ -207,7 +208,21 @@ export default function Settings() {
.sort((aConf, bConf) => aConf.ui.order - bConf.ui.order); .sort((aConf, bConf) => aConf.ui.order - bConf.ui.order);
}, [config]); }, [config]);
const [selectedCamera, setSelectedCamera] = useState<string>(""); const [persistedCamera, setPersistedCamera] = usePersistence(
"selectedCamera",
"",
);
const [selectedCamera, setSelectedCamera] = useState(persistedCamera);
useEffect(() => {
if (persistedCamera) {
setSelectedCamera(persistedCamera);
}
}, [persistedCamera]);
useEffect(() => {
if (selectedCamera) {
setPersistedCamera(selectedCamera);
}
}, [selectedCamera, setPersistedCamera]);
const { payload: allCameraStates } = useInitialCameraState( const { payload: allCameraStates } = useInitialCameraState(
cameras.length > 0 ? cameras[0].name : "", cameras.length > 0 ? cameras[0].name : "",