add UI setting to configure jsmpeg fallback timeout

This commit is contained in:
Josh Hawkins 2025-11-10 18:19:40 -06:00
parent 3392039185
commit 0b43c15602
3 changed files with 60 additions and 3 deletions

View File

@ -8,7 +8,7 @@
"masksAndZones": "Mask and Zone Editor - Frigate",
"motionTuner": "Motion Tuner - Frigate",
"object": "Debug - Frigate",
"general": "General Settings - Frigate",
"general": "UI Settings - Frigate",
"frigatePlus": "Frigate+ Settings - Frigate",
"notifications": "Notification Settings - Frigate"
},
@ -37,7 +37,7 @@
"noCamera": "No Camera"
},
"general": {
"title": "General Settings",
"title": "UI Settings",
"liveDashboard": {
"title": "Live Dashboard",
"automaticLiveView": {
@ -51,6 +51,10 @@
"displayCameraNames": {
"label": "Always Show Camera Names",
"desc": "Always show the camera names in a chip in the multi-camera live view dashboard."
},
"liveFallbackTimeout": {
"label": "Live Player Fallback Timeout",
"desc": "When a camera's high quality live stream is unavailable, fall back to low bandwidth mode after this many seconds. Default: 3."
}
},
"storedLayouts": {

View File

@ -1,4 +1,5 @@
import { baseUrl } from "@/api/baseUrl";
import { usePersistence } from "@/hooks/use-persistence";
import {
LivePlayerError,
PlayerStatsType,
@ -71,6 +72,8 @@ function MSEPlayer({
const [errorCount, setErrorCount] = useState<number>(0);
const totalBytesLoaded = useRef(0);
const [fallbackTimeout] = usePersistence<number>("liveFallbackTimeout", 3);
const videoRef = useRef<HTMLVideoElement>(null);
const wsRef = useRef<WebSocket | null>(null);
const reconnectTIDRef = useRef<number | null>(null);
@ -475,7 +478,10 @@ function MSEPlayer({
setBufferTimeout(undefined);
}
const timeoutDuration = bufferTime == 0 ? 5000 : 3000;
const timeoutDuration =
bufferTime == 0
? (fallbackTimeout ?? 3) * 2 * 1000
: (fallbackTimeout ?? 3) * 1000;
setBufferTimeout(
setTimeout(() => {
if (
@ -500,6 +506,7 @@ function MSEPlayer({
onError,
onPlaying,
playbackEnabled,
fallbackTimeout,
]);
useEffect(() => {

View File

@ -99,6 +99,10 @@ export default function UiSettingsView() {
const [playbackRate, setPlaybackRate] = usePersistence("playbackRate", 1);
const [weekStartsOn, setWeekStartsOn] = usePersistence("weekStartsOn", 0);
const [alertVideos, setAlertVideos] = usePersistence("alertVideos", true);
const [fallbackTimeout, setFallbackTimeout] = usePersistence(
"liveFallbackTimeout",
3,
);
return (
<>
@ -161,6 +165,48 @@ export default function UiSettingsView() {
<p>{t("general.liveDashboard.displayCameraNames.desc")}</p>
</div>
</div>
<div className="space-y-3">
<div className="flex flex-row items-center justify-start gap-2">
<Label
className="cursor-pointer"
htmlFor="live-fallback-timeout"
>
{t("general.liveDashboard.liveFallbackTimeout.label")}
</Label>
</div>
<div className="my-2 max-w-5xl text-sm text-muted-foreground">
<p>{t("general.liveDashboard.liveFallbackTimeout.desc")}</p>
</div>
<Select
value={fallbackTimeout?.toString()}
onValueChange={(value) => setFallbackTimeout(parseInt(value))}
>
<SelectTrigger className="w-36">
{t("time.second", {
ns: "common",
time: fallbackTimeout,
count: fallbackTimeout,
})}
</SelectTrigger>
<SelectContent>
<SelectGroup>
{[1, 2, 3, 4, 5, 6, 7, 8, 9, 10].map((timeout) => (
<SelectItem
key={timeout}
className="cursor-pointer"
value={timeout.toString()}
>
{t("time.second", {
ns: "common",
time: timeout,
count: timeout,
})}
</SelectItem>
))}
</SelectGroup>
</SelectContent>
</Select>
</div>
</div>
<div className="my-3 flex w-full flex-col space-y-6">