mirror of
https://github.com/blakeblackshear/frigate.git
synced 2026-04-11 09:37:37 +03:00
look for backchannel on all registered streams on save
avoids potential issues with a timeout in stream registration
This commit is contained in:
parent
224bf16a4a
commit
c7f99ee37c
@ -42,6 +42,9 @@ export default function Step4Validation({
|
|||||||
const [measuredBandwidth, setMeasuredBandwidth] = useState<
|
const [measuredBandwidth, setMeasuredBandwidth] = useState<
|
||||||
Map<string, number>
|
Map<string, number>
|
||||||
>(new Map());
|
>(new Map());
|
||||||
|
const [registeredStreamIds, setRegisteredStreamIds] = useState<
|
||||||
|
Map<string, string>
|
||||||
|
>(new Map());
|
||||||
|
|
||||||
const streams = useMemo(() => wizardData.streams || [], [wizardData.streams]);
|
const streams = useMemo(() => wizardData.streams || [], [wizardData.streams]);
|
||||||
|
|
||||||
@ -127,15 +130,10 @@ export default function Step4Validation({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const checkBackchannel = useCallback(
|
const checkBackchannel = useCallback(
|
||||||
async (go2rtcStreamId: string, useFfmpeg: boolean) => {
|
async (go2rtcStreamId: string, useFfmpeg: boolean): Promise<boolean> => {
|
||||||
if (wizardData.hasBackchannel !== undefined) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ffmpeg compatibility mode guarantees no backchannel connection
|
// ffmpeg compatibility mode guarantees no backchannel connection
|
||||||
if (useFfmpeg) {
|
if (useFfmpeg) {
|
||||||
onUpdate({ hasBackchannel: false });
|
return false;
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@ -144,12 +142,12 @@ export default function Step4Validation({
|
|||||||
);
|
);
|
||||||
|
|
||||||
const audioFeatures = detectCameraAudioFeatures(response.data, false);
|
const audioFeatures = detectCameraAudioFeatures(response.data, false);
|
||||||
onUpdate({ hasBackchannel: audioFeatures.twoWayAudio });
|
return audioFeatures.twoWayAudio;
|
||||||
} catch {
|
} catch {
|
||||||
onUpdate({ hasBackchannel: false });
|
return false;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[wizardData.hasBackchannel, onUpdate],
|
[],
|
||||||
);
|
);
|
||||||
|
|
||||||
const validateStream = useCallback(
|
const validateStream = useCallback(
|
||||||
@ -235,12 +233,31 @@ export default function Step4Validation({
|
|||||||
}
|
}
|
||||||
}, [streams, onUpdate, t, performStreamValidation]);
|
}, [streams, onUpdate, t, performStreamValidation]);
|
||||||
|
|
||||||
const handleSave = useCallback(() => {
|
const handleSave = useCallback(async () => {
|
||||||
if (!wizardData.cameraName || !wizardData.streams?.length) {
|
if (!wizardData.cameraName || !wizardData.streams?.length) {
|
||||||
toast.error(t("cameraWizard.step4.saveError"));
|
toast.error(t("cameraWizard.step4.saveError"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const candidateStreams =
|
||||||
|
wizardData.streams?.filter(
|
||||||
|
(s) => s.testResult?.success && !(s.useFfmpeg ?? false),
|
||||||
|
) || [];
|
||||||
|
|
||||||
|
let hasBackchannelResult = false;
|
||||||
|
if (candidateStreams.length > 0) {
|
||||||
|
// Check all candidate streams for backchannel support
|
||||||
|
const backchanelChecks = candidateStreams.map((stream) => {
|
||||||
|
const actualStreamId = registeredStreamIds.get(stream.id);
|
||||||
|
return actualStreamId
|
||||||
|
? checkBackchannel(actualStreamId, stream.useFfmpeg ?? false)
|
||||||
|
: Promise.resolve(false);
|
||||||
|
});
|
||||||
|
const results = await Promise.all(backchanelChecks);
|
||||||
|
hasBackchannelResult = results.some((result) => result);
|
||||||
|
}
|
||||||
|
onUpdate({ hasBackchannel: hasBackchannelResult });
|
||||||
|
|
||||||
// Convert wizard data to final config format
|
// Convert wizard data to final config format
|
||||||
const configData = {
|
const configData = {
|
||||||
cameraName: wizardData.cameraName,
|
cameraName: wizardData.cameraName,
|
||||||
@ -254,7 +271,7 @@ export default function Step4Validation({
|
|||||||
};
|
};
|
||||||
|
|
||||||
onSave(configData);
|
onSave(configData);
|
||||||
}, [wizardData, onSave, t]);
|
}, [wizardData, onSave, t, onUpdate, checkBackchannel, registeredStreamIds]);
|
||||||
|
|
||||||
const canSave = useMemo(() => {
|
const canSave = useMemo(() => {
|
||||||
return (
|
return (
|
||||||
@ -353,9 +370,8 @@ export default function Step4Validation({
|
|||||||
stream={stream}
|
stream={stream}
|
||||||
onBandwidthUpdate={handleBandwidthUpdate}
|
onBandwidthUpdate={handleBandwidthUpdate}
|
||||||
onStreamRegistered={(go2rtcStreamId) => {
|
onStreamRegistered={(go2rtcStreamId) => {
|
||||||
checkBackchannel(
|
setRegisteredStreamIds((prev) =>
|
||||||
go2rtcStreamId,
|
new Map(prev).set(stream.id, go2rtcStreamId),
|
||||||
stream.useFfmpeg ?? false,
|
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
@ -763,9 +779,10 @@ function StreamPreview({
|
|||||||
})
|
})
|
||||||
.then(async () => {
|
.then(async () => {
|
||||||
// Add small delay to allow go2rtc api to run and initialize the stream
|
// Add small delay to allow go2rtc api to run and initialize the stream
|
||||||
await new Promise((resolve) => setTimeout(resolve, 1000));
|
setTimeout(() => {
|
||||||
setRegistered(true);
|
setRegistered(true);
|
||||||
onStreamRegistered?.(streamId);
|
onStreamRegistered?.(streamId);
|
||||||
|
}, 500);
|
||||||
})
|
})
|
||||||
.catch(() => {
|
.catch(() => {
|
||||||
setError(true);
|
setError(true);
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user