keep using ffmpeg module

This commit is contained in:
Josh Hawkins
2026-10-06 08:18:06 -05:00
parent 3180d63df1
commit f8935ec1b2
8 changed files with 60 additions and 24 deletions
@@ -3,7 +3,8 @@
*
* The wizard asks the camera for its resolution, then probes http-flv first
* above 5MP and falls back to RTSP. The Step 4 RTSP warning is only for
* cameras that should be on http-flv.
* cameras that should be on http-flv. An http-flv stream the wizard selects
* is registered with go2rtc through the ffmpeg module.
*/
import { test, expect } from "../../fixtures/frigate-test";
@@ -12,6 +13,7 @@ import type { Page } from "@playwright/test";
const FLV_PATH = "channel0_main.bcs";
const RTSP_PATH = "Preview_01_main";
const RTSP_WARNING = "Reolink RTSP is not recommended";
const HTTP_WARNING = "Reolink HTTP streams should use FFmpeg";
const FFPROBE_OK = [
{
@@ -105,6 +107,20 @@ test.describe("Camera wizard Reolink stream selection @medium @mobile", () => {
expect(probed).toEqual([FLV_PATH]);
await expect(dialog.locator(`input[value*="${FLV_PATH}"]`)).toBeVisible();
const registered: string[] = [];
await frigateApp.page.route("**/api/go2rtc/streams/**", (route) => {
const src = new URL(route.request().url()).searchParams.get("src");
if (src) registered.push(src);
return route.fulfill({ json: {} });
});
await dialog.getByRole("button", { name: /^Next$/i }).click();
await expect(
dialog.getByRole("button", { name: /Save New Camera/i }),
).toBeVisible();
await expect.poll(() => registered[0]).toMatch(/^ffmpeg:http:\/\//);
await expect(dialog.getByText(HTTP_WARNING)).toHaveCount(0);
});
test("above 5MP falls back to RTSP without a warning", async ({
+2 -1
View File
@@ -505,7 +505,8 @@
"audioCodecRequired": "An audio stream is required to support audio detection.",
"restreamingWarning": "Reducing connections to the camera for the record stream may increase CPU usage slightly.",
"brands": {
"reolink-rtsp": "Reolink RTSP is not recommended. Enable HTTP in the camera's firmware settings and restart the wizard."
"reolink-rtsp": "Reolink RTSP is not recommended. Enable HTTP in the camera's firmware settings and restart the wizard.",
"reolink-http": "Reolink HTTP streams should use FFmpeg for better compatibility. Enable 'Use stream compatibility mode' for this stream."
},
"dahua": {
"substreamWarning": "Substream 1 is locked to a low resolution. Many Dahua / Amcrest / EmpireTech cameras support additional substreams that need to be enabled in the camera's settings. It is recommended to check and utilize those streams if available."
@@ -393,6 +393,9 @@ export default function Step2ProbeOrSnapshot({
url: streamUrl,
roles: ["detect"] as StreamRole[],
testResult: result,
useFfmpeg:
wizardData.brandTemplate === "reolink" &&
streamUrl.startsWith("http://"),
},
],
});
@@ -500,6 +500,7 @@ function StreamIssues({
roles: stream.roles,
brand: wizardData.brandTemplate,
reolinkProtocol: wizardData.reolinkProtocol,
useFfmpeg: stream.useFfmpeg,
restream: stream.restream,
testResult: stream.testResult,
},
+2 -1
View File
@@ -12,7 +12,7 @@ import {
} from "@/utils/streamIssues";
// rules the add camera wizard shows that do not belong on the Health tab
const WIZARD_ONLY_RULES = new Set(["restream", "reolink-rtsp"]);
const WIZARD_ONLY_RULES = new Set(["restream", "reolink-rtsp", "reolink-http"]);
/**
* Whether the record output keeps the camera's audio codec. The default
@@ -115,6 +115,7 @@ export function streamHealth(
url,
roles: input.roles as StreamRole[],
brand: inferCameraBrand(url),
useFfmpeg: restream?.useFfmpeg,
restream: !!restream,
testResult: result,
},
+28 -15
View File
@@ -14,6 +14,7 @@ export type StreamIssueInput = {
roles: StreamRole[];
brand?: CameraBrand;
reolinkProtocol?: "http-flv" | "rtsp" | null;
useFfmpeg?: boolean;
restream?: boolean;
testResult?: TestResult;
};
@@ -94,18 +95,27 @@ export function getStreamIssues(
const result: StreamIssue[] = [];
const { roles, testResult } = input;
if (
input.brand === "reolink" &&
input.reolinkProtocol !== "rtsp" &&
input.url.toLowerCase().startsWith("rtsp://")
) {
result.push({
type: "warning",
rule: "reolink-rtsp",
message: t("cameraWizard.step4.issues.brands.reolink-rtsp", {
ns: "views/settings",
}),
});
if (input.brand === "reolink") {
const streamUrl = input.url.toLowerCase();
if (streamUrl.startsWith("rtsp://") && input.reolinkProtocol !== "rtsp") {
result.push({
type: "warning",
rule: "reolink-rtsp",
message: t("cameraWizard.step4.issues.brands.reolink-rtsp", {
ns: "views/settings",
}),
});
}
if (streamUrl.startsWith("http://") && !input.useFfmpeg) {
result.push({
type: "warning",
rule: "reolink-http",
message: t("cameraWizard.step4.issues.brands.reolink-http", {
ns: "views/settings",
}),
});
}
}
if (testResult?.videoCodec) {
@@ -259,7 +269,7 @@ export function getStreamIssues(
export function resolveRestreamSource(
path: string,
streams: Record<string, string | string[]> | undefined,
): { url: string } | undefined {
): { url: string; useFfmpeg: boolean } | undefined {
const name = parseRestreamStreamName(path);
if (!name || !streams) {
@@ -279,8 +289,11 @@ export function resolveRestreamSource(
}
if (source.startsWith("ffmpeg:")) {
return { url: source.slice("ffmpeg:".length).split("#")[0] };
return {
url: source.slice("ffmpeg:".length).split("#")[0],
useFfmpeg: true,
};
}
return { url: source };
return { url: source, useFfmpeg: false };
}