mirror of
https://github.com/blakeblackshear/frigate.git
synced 2025-12-12 16:16:42 +03:00
consolidate validation logic
This commit is contained in:
parent
e9459c5e29
commit
44ff205966
@ -151,8 +151,8 @@ export default function Step3Validation({
|
|||||||
return results;
|
return results;
|
||||||
}, [streams]);
|
}, [streams]);
|
||||||
|
|
||||||
const validateStream = useCallback(
|
const performStreamValidation = useCallback(
|
||||||
async (stream: StreamConfig) => {
|
async (stream: StreamConfig): Promise<TestResult> => {
|
||||||
try {
|
try {
|
||||||
const response = await axios.get("ffprobe", {
|
const response = await axios.get("ffprobe", {
|
||||||
params: { paths: stream.url, detailed: true },
|
params: { paths: stream.url, detailed: true },
|
||||||
@ -186,38 +186,16 @@ export default function Step3Validation({
|
|||||||
parseFloat(videoStream.r_frame_rate.split("/")[1])
|
parseFloat(videoStream.r_frame_rate.split("/")[1])
|
||||||
: undefined;
|
: undefined;
|
||||||
|
|
||||||
const testResult: TestResult = {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
resolution,
|
resolution,
|
||||||
videoCodec: videoStream?.codec_name,
|
videoCodec: videoStream?.codec_name,
|
||||||
audioCodec: audioStream?.codec_name,
|
audioCodec: audioStream?.codec_name,
|
||||||
fps: fps && !isNaN(fps) ? fps : undefined,
|
fps: fps && !isNaN(fps) ? fps : undefined,
|
||||||
};
|
};
|
||||||
|
|
||||||
onUpdate({
|
|
||||||
streams: streams.map((s) =>
|
|
||||||
s.id === stream.id ? { ...s, testResult } : s,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
toast.success(
|
|
||||||
t("cameraWizard.step3.streamValidated", {
|
|
||||||
number: streams.findIndex((s) => s.id === stream.id) + 1,
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
} else {
|
} else {
|
||||||
const error = response.data?.[0]?.stderr || "Unknown error";
|
const error = response.data?.[0]?.stderr || "Unknown error";
|
||||||
const testResult: TestResult = { success: false, error };
|
return { success: false, error };
|
||||||
|
|
||||||
onUpdate({
|
|
||||||
streams: streams.map((s) =>
|
|
||||||
s.id === stream.id ? { ...s, testResult } : s,
|
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
toast.error(
|
|
||||||
`Stream ${streams.findIndex((s) => s.id === stream.id) + 1} validation failed`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const axiosError = error as {
|
const axiosError = error as {
|
||||||
@ -230,14 +208,29 @@ export default function Step3Validation({
|
|||||||
axiosError.message ||
|
axiosError.message ||
|
||||||
"Connection failed";
|
"Connection failed";
|
||||||
|
|
||||||
const testResult: TestResult = { success: false, error: errorMessage };
|
return { success: false, error: errorMessage };
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[],
|
||||||
|
);
|
||||||
|
|
||||||
onUpdate({
|
const validateStream = useCallback(
|
||||||
streams: streams.map((s) =>
|
async (stream: StreamConfig) => {
|
||||||
s.id === stream.id ? { ...s, testResult } : s,
|
const testResult = await performStreamValidation(stream);
|
||||||
),
|
|
||||||
});
|
|
||||||
|
|
||||||
|
onUpdate({
|
||||||
|
streams: streams.map((s) =>
|
||||||
|
s.id === stream.id ? { ...s, testResult } : s,
|
||||||
|
),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (testResult.success) {
|
||||||
|
toast.success(
|
||||||
|
t("cameraWizard.step3.streamValidated", {
|
||||||
|
number: streams.findIndex((s) => s.id === stream.id) + 1,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
toast.error(
|
toast.error(
|
||||||
t("cameraWizard.step3.streamValidationFailed", {
|
t("cameraWizard.step3.streamValidationFailed", {
|
||||||
number: streams.findIndex((s) => s.id === stream.id) + 1,
|
number: streams.findIndex((s) => s.id === stream.id) + 1,
|
||||||
@ -245,7 +238,7 @@ export default function Step3Validation({
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
[streams, onUpdate, t],
|
[streams, onUpdate, t, performStreamValidation],
|
||||||
);
|
);
|
||||||
|
|
||||||
const validateAllStreams = useCallback(async () => {
|
const validateAllStreams = useCallback(async () => {
|
||||||
@ -260,64 +253,8 @@ export default function Step3Validation({
|
|||||||
for (const stream of streamsToTest) {
|
for (const stream of streamsToTest) {
|
||||||
if (!stream.url.trim()) continue;
|
if (!stream.url.trim()) continue;
|
||||||
|
|
||||||
try {
|
const testResult = await performStreamValidation(stream);
|
||||||
const response = await axios.get("ffprobe", {
|
results.set(stream.id, testResult);
|
||||||
params: { paths: stream.url, detailed: true },
|
|
||||||
timeout: 10000,
|
|
||||||
});
|
|
||||||
|
|
||||||
if (response.data?.[0]?.return_code === 0) {
|
|
||||||
const probeData = response.data[0];
|
|
||||||
const streamData = probeData.stdout.streams || [];
|
|
||||||
|
|
||||||
const videoStream = streamData.find(
|
|
||||||
(s: { codec_type?: string; codec_name?: string }) =>
|
|
||||||
s.codec_type === "video" ||
|
|
||||||
s.codec_name?.includes("h264") ||
|
|
||||||
s.codec_name?.includes("h265"),
|
|
||||||
);
|
|
||||||
|
|
||||||
const audioStream = streamData.find(
|
|
||||||
(s: { codec_type?: string; codec_name?: string }) =>
|
|
||||||
s.codec_type === "audio" ||
|
|
||||||
s.codec_name?.includes("aac") ||
|
|
||||||
s.codec_name?.includes("mp3"),
|
|
||||||
);
|
|
||||||
|
|
||||||
const resolution = videoStream
|
|
||||||
? `${videoStream.width}x${videoStream.height}`
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const fps = videoStream?.r_frame_rate
|
|
||||||
? parseFloat(videoStream.r_frame_rate.split("/")[0]) /
|
|
||||||
parseFloat(videoStream.r_frame_rate.split("/")[1])
|
|
||||||
: undefined;
|
|
||||||
|
|
||||||
const testResult: TestResult = {
|
|
||||||
success: true,
|
|
||||||
resolution,
|
|
||||||
videoCodec: videoStream?.codec_name,
|
|
||||||
audioCodec: audioStream?.codec_name,
|
|
||||||
fps: fps && !isNaN(fps) ? fps : undefined,
|
|
||||||
};
|
|
||||||
|
|
||||||
results.set(stream.id, testResult);
|
|
||||||
} else {
|
|
||||||
const error = response.data?.[0]?.stderr || "Unknown error";
|
|
||||||
results.set(stream.id, { success: false, error });
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
const axiosError = error as {
|
|
||||||
response?: { data?: { message?: string; detail?: string } };
|
|
||||||
message?: string;
|
|
||||||
};
|
|
||||||
const errorMessage =
|
|
||||||
axiosError.response?.data?.message ||
|
|
||||||
axiosError.response?.data?.detail ||
|
|
||||||
axiosError.message ||
|
|
||||||
"Connection failed";
|
|
||||||
results.set(stream.id, { success: false, error: errorMessage });
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update wizard data with new test results
|
// Update wizard data with new test results
|
||||||
@ -345,7 +282,7 @@ export default function Step3Validation({
|
|||||||
toast.warning(t("cameraWizard.step3.validationPartial"));
|
toast.warning(t("cameraWizard.step3.validationPartial"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}, [streams, onUpdate, t]);
|
}, [streams, onUpdate, t, performStreamValidation]);
|
||||||
|
|
||||||
const handleSave = useCallback(() => {
|
const handleSave = useCallback(() => {
|
||||||
if (!wizardData.cameraName || !wizardData.streams?.length) {
|
if (!wizardData.cameraName || !wizardData.streams?.length) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user