Add camera wizard improvements (#22963)

* warn in camera wizard when detect stream resolution cannot be determined

* add timeout and tcp fallback for rtsp urls only
This commit is contained in:
Josh Hawkins 2026-04-22 08:15:17 -05:00 committed by GitHub
parent 2dcaeb6809
commit f4ac063b37
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 36 additions and 9 deletions

View File

@ -807,10 +807,15 @@ async def get_video_properties(
) -> dict[str, Any]:
async def probe_with_ffprobe(
url: str,
rtsp_transport: Optional[str] = None,
) -> tuple[bool, int, int, Optional[str], float]:
"""Fallback using ffprobe: returns (valid, width, height, codec, duration)."""
cmd = [
ffmpeg.ffprobe_path,
cmd = [ffmpeg.ffprobe_path]
if rtsp_transport:
cmd += ["-rtsp_transport", rtsp_transport]
cmd += [
"-rw_timeout",
"5000000",
"-v",
"quiet",
"-print_format",
@ -879,6 +884,12 @@ async def get_video_properties(
if not has_video or (get_duration and duration < 0):
has_video, width, height, fourcc, duration = await probe_with_ffprobe(url)
# last resort for RTSP: try TCP transport, since default UDP may be blocked
if (not has_video or (get_duration and duration < 0)) and url.startswith("rtsp://"):
has_video, width, height, fourcc, duration = await probe_with_ffprobe(
url, rtsp_transport="tcp"
)
result: dict[str, Any] = {"has_valid_video": has_video}
if has_video:
result.update({"width": width, "height": height})

View File

@ -415,6 +415,7 @@
"audioCodecGood": "Audio codec is {{codec}}.",
"resolutionHigh": "A resolution of {{resolution}} may cause increased resource usage.",
"resolutionLow": "A resolution of {{resolution}} may be too low for reliable detection of small objects.",
"resolutionUnknown": "The resolution of this stream could not be probed. This will cause issues on startup. You should manually set the detect resolution in Settings or your config.",
"noAudioWarning": "No audio detected for this stream, recordings will not have audio.",
"audioCodecRecordError": "The AAC audio codec is required to support audio in recordings.",
"audioCodecRequired": "An audio stream is required to support audio detection.",

View File

@ -607,23 +607,38 @@ function StreamIssues({
}
}
if (stream.roles.includes("detect") && stream.resolution) {
const [width, height] = stream.resolution.split("x").map(Number);
if (!isNaN(width) && !isNaN(height) && width > 0 && height > 0) {
const minDimension = Math.min(width, height);
const maxDimension = Math.max(width, height);
if (stream.roles.includes("detect") && stream.testResult) {
const probedResolution = stream.testResult.resolution;
let probedWidth = 0;
let probedHeight = 0;
if (probedResolution) {
const [w, h] = probedResolution.split("x").map(Number);
if (!isNaN(w) && !isNaN(h)) {
probedWidth = w;
probedHeight = h;
}
}
if (probedWidth <= 0 || probedHeight <= 0) {
result.push({
type: "error",
message: t("cameraWizard.step4.issues.resolutionUnknown"),
});
} else {
const minDimension = Math.min(probedWidth, probedHeight);
const maxDimension = Math.max(probedWidth, probedHeight);
if (minDimension > 1080) {
result.push({
type: "warning",
message: t("cameraWizard.step4.issues.resolutionHigh", {
resolution: stream.resolution,
resolution: probedResolution,
}),
});
} else if (maxDimension < 640) {
result.push({
type: "error",
message: t("cameraWizard.step4.issues.resolutionLow", {
resolution: stream.resolution,
resolution: probedResolution,
}),
});
}