add capabilities to live mode hook

This commit is contained in:
Josh Hawkins 2024-12-22 12:25:07 -06:00
parent 33a1f82fe8
commit 84fcc56fef

View File

@ -1,16 +1,29 @@
import { CameraConfig, FrigateConfig } from "@/types/frigateConfig"; import { CameraConfig, FrigateConfig } from "@/types/frigateConfig";
import { useCallback, useEffect, useState } from "react"; import { useCallback, useEffect, useState } from "react";
import useSWR from "swr"; import useSWR from "swr";
import { LivePlayerMode } from "@/types/live"; import { LivePlayerMode, LiveStreamMetadata } from "@/types/live";
export default function useCameraLiveMode( export default function useCameraLiveMode(
cameras: CameraConfig[], cameras: CameraConfig[],
windowVisible: boolean, windowVisible: boolean,
) { ) {
const { data: config } = useSWR<FrigateConfig>("config"); const { data: config } = useSWR<FrigateConfig>("config");
const { data: allStreamMetadata } = useSWR<{
[key: string]: LiveStreamMetadata;
}>(config ? "go2rtc/streams" : null, { revalidateOnFocus: false });
const [preferredLiveModes, setPreferredLiveModes] = useState<{ const [preferredLiveModes, setPreferredLiveModes] = useState<{
[key: string]: LivePlayerMode; [key: string]: LivePlayerMode;
}>({}); }>({});
const [isRestreamedStates, setIsRestreamedStates] = useState<{
[key: string]: boolean;
}>({});
const [supportsAudioOutputStates, setSupportsAudioOutputStates] = useState<{
[key: string]: {
supportsAudio: boolean;
cameraName: string;
};
}>({});
useEffect(() => { useEffect(() => {
if (!cameras) return; if (!cameras) return;
@ -18,26 +31,56 @@ export default function useCameraLiveMode(
const mseSupported = const mseSupported =
"MediaSource" in window || "ManagedMediaSource" in window; "MediaSource" in window || "ManagedMediaSource" in window;
const newPreferredLiveModes = cameras.reduce( const newPreferredLiveModes: { [key: string]: LivePlayerMode } = {};
(acc, camera) => { const newIsRestreamedStates: { [key: string]: boolean } = {};
const isRestreamed = const newSupportsAudioOutputStates: {
config && [key: string]: { supportsAudio: boolean; cameraName: string };
Object.keys(config.go2rtc.streams || {}).includes( } = {};
Object.values(camera.live.streams)[0],
);
if (!mseSupported) { cameras.forEach((camera) => {
acc[camera.name] = isRestreamed ? "webrtc" : "jsmpeg"; const isRestreamed =
} else { config &&
acc[camera.name] = isRestreamed ? "mse" : "jsmpeg"; Object.keys(config.go2rtc.streams || {}).includes(
} Object.values(camera.live.streams)[0],
return acc; );
},
{} as { [key: string]: LivePlayerMode }, newIsRestreamedStates[camera.name] = isRestreamed ?? false;
);
if (!mseSupported) {
newPreferredLiveModes[camera.name] = isRestreamed ? "webrtc" : "jsmpeg";
} else {
newPreferredLiveModes[camera.name] = isRestreamed ? "mse" : "jsmpeg";
}
// check each stream for audio support
if (isRestreamed) {
Object.values(camera.live.streams).forEach((streamName) => {
const metadata = allStreamMetadata?.[streamName];
newSupportsAudioOutputStates[streamName] = {
supportsAudio: metadata
? metadata.producers.find(
(prod) =>
prod.medias &&
prod.medias.find((media) =>
media.includes("audio, recvonly"),
) !== undefined,
) !== undefined
: false,
cameraName: camera.name,
};
});
} else {
newSupportsAudioOutputStates[camera.name] = {
supportsAudio: false,
cameraName: camera.name,
};
}
});
setPreferredLiveModes(newPreferredLiveModes); setPreferredLiveModes(newPreferredLiveModes);
}, [cameras, config, windowVisible]); setIsRestreamedStates(newIsRestreamedStates);
setSupportsAudioOutputStates(newSupportsAudioOutputStates);
}, [cameras, config, windowVisible, allStreamMetadata]);
const resetPreferredLiveMode = useCallback( const resetPreferredLiveMode = useCallback(
(cameraName: string) => { (cameraName: string) => {
@ -61,5 +104,11 @@ export default function useCameraLiveMode(
[config], [config],
); );
return { preferredLiveModes, setPreferredLiveModes, resetPreferredLiveMode }; return {
preferredLiveModes,
setPreferredLiveModes,
resetPreferredLiveMode,
isRestreamedStates,
supportsAudioOutputStates,
};
} }