diff --git a/web/src/App.tsx b/web/src/App.tsx index 46fcc5b64..15ad1e2be 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -36,7 +36,7 @@ function App() { > } /> - } /> + } /> } /> } /> } /> diff --git a/web/src/components/Chip.tsx b/web/src/components/Chip.tsx new file mode 100644 index 000000000..8333a8f78 --- /dev/null +++ b/web/src/components/Chip.tsx @@ -0,0 +1,13 @@ +import { ReactNode } from "react"; + +type ChipProps = { + className?: string; + children?: ReactNode[]; +}; +export default function Chip({ className, children }: ChipProps) { + return ( +
+ {children} +
+ ); +} diff --git a/web/src/components/player/LivePlayer.tsx b/web/src/components/player/LivePlayer.tsx index 44f3cf975..12af0bff8 100644 --- a/web/src/components/player/LivePlayer.tsx +++ b/web/src/components/player/LivePlayer.tsx @@ -12,12 +12,15 @@ import { usePersistence } from "@/hooks/use-persistence"; import MSEPlayer from "./MsePlayer"; import JSMpegPlayer from "./JSMpegPlayer"; import useSWR from "swr"; +import { MdCircle } from "react-icons/md"; +import Chip from "../Chip"; const emptyObject = Object.freeze({}); type LivePlayerProps = { className?: string; cameraConfig: CameraConfig; + liveMode?: "webrtc" | "mse" | "jsmpeg" | "debug"; }; type Options = { [key: string]: boolean }; @@ -25,6 +28,7 @@ type Options = { [key: string]: boolean }; export default function LivePlayer({ className, cameraConfig, + liveMode = "mse", }: LivePlayerProps) { const { data: config } = useSWR("config"); const [showSettings, setShowSettings] = useState(false); @@ -34,35 +38,6 @@ export default function LivePlayer({ emptyObject ); - const restreamEnabled = useMemo(() => { - if (!config) { - return false; - } - - return ( - cameraConfig && - Object.keys(config.go2rtc.streams || {}).includes( - cameraConfig.live.stream_name - ) - ); - }, [config, cameraConfig]); - - const defaultLiveMode = useMemo(() => { - if (cameraConfig) { - if (restreamEnabled) { - return cameraConfig.ui.live_mode || config?.ui.live_mode; - } - - return "jsmpeg"; - } - - return undefined; - }, [cameraConfig, restreamEnabled]); - const [liveMode, setLiveMode, sourceIsLoaded] = usePersistence( - `${cameraConfig.name}-source`, - defaultLiveMode - ); - const handleSetOption = useCallback( (id: string, value: boolean) => { const newOptions = { ...options, [id]: value }; @@ -91,24 +66,24 @@ export default function LivePlayer({ return ; } + let player; if (liveMode == "webrtc") { - return ( -
- -
+ player = ( + ); } else if (liveMode == "mse") { if ("MediaSource" in window || "ManagedMediaSource" in window) { - return ( -
- -
+ player = ( + ); } else { - return ( + player = (
MSE is only supported on iOS 17.1+. You'll need to update if available or use jsmpeg / webRTC streams. See the docs for more info. @@ -116,17 +91,15 @@ export default function LivePlayer({ ); } } else if (liveMode == "jsmpeg") { - return ( -
- -
+ player = ( + ); } else if (liveMode == "debug") { - return ( + player = ( <> ); } else { - ; + player = ; } + + return ( +
+ {player} + + +
+ {cameraConfig.name.replaceAll("_", " ")} +
+
+
+ ); } type DebugSettingsProps = { diff --git a/web/src/components/player/MsePlayer.tsx b/web/src/components/player/MsePlayer.tsx index d1630ca75..f3b41acb5 100644 --- a/web/src/components/player/MsePlayer.tsx +++ b/web/src/components/player/MsePlayer.tsx @@ -3,9 +3,10 @@ import { useCallback, useEffect, useMemo, useRef, useState } from "react"; type MSEPlayerProps = { camera: string; + className?: string; }; -function MSEPlayer({ camera }: MSEPlayerProps) { +function MSEPlayer({ camera, className }: MSEPlayerProps) { let connectTS: number = 0; const RECONNECT_TIMEOUT: number = 30000; @@ -246,6 +247,7 @@ function MSEPlayer({ camera }: MSEPlayerProps) { return (