diff --git a/src/OpenIPC.Viewer.App/Services/Localizer.cs b/src/OpenIPC.Viewer.App/Services/Localizer.cs
index e4d8d5b..12083d1 100644
--- a/src/OpenIPC.Viewer.App/Services/Localizer.cs
+++ b/src/OpenIPC.Viewer.App/Services/Localizer.cs
@@ -340,8 +340,8 @@ private static LangCode DetectSystem()
["CameraEditor.Placeholder.SshPort"] = "22",
["CameraEditor.NoGroup"] = "(no group)",
["CameraEditor.Button.AutoDeriveRtsp"] = "Auto from host",
- ["CameraEditor.Button.AutoDeriveXmRtsp"] = "XM preset",
- ["CameraEditor.Tooltip.AutoDeriveXmRtsp"] = "Fill in the RTSP URLs used by XM/Xiongmai (NETSurveillance) cameras",
+ ["CameraEditor.Button.RtspTemplates"] = "Templates ▾",
+ ["CameraEditor.Tooltip.RtspTemplates"] = "Fill in the RTSP URLs used by a specific camera vendor",
["CameraEditor.Button.TestConnection"] = "Test connection",
["CameraEditor.Status.Connecting"] = "Connecting…",
["CameraEditor.Status.OkFormat"] = "OK — {0}x{1}",
@@ -811,8 +811,8 @@ private static LangCode DetectSystem()
["CameraEditor.Placeholder.SshPort"] = "22",
["CameraEditor.NoGroup"] = "(без группы)",
["CameraEditor.Button.AutoDeriveRtsp"] = "Подставить из хоста",
- ["CameraEditor.Button.AutoDeriveXmRtsp"] = "Пресет XM",
- ["CameraEditor.Tooltip.AutoDeriveXmRtsp"] = "Подставить RTSP-адреса камер XM/Xiongmai (NETSurveillance)",
+ ["CameraEditor.Button.RtspTemplates"] = "Шаблоны ▾",
+ ["CameraEditor.Tooltip.RtspTemplates"] = "Подставить RTSP-адреса под конкретного производителя камеры",
["CameraEditor.Button.TestConnection"] = "Проверить",
["CameraEditor.Status.Connecting"] = "Подключение…",
["CameraEditor.Status.OkFormat"] = "OK — {0}x{1}",
diff --git a/src/OpenIPC.Viewer.App/ViewModels/Dialogs/CameraEditorViewModel.cs b/src/OpenIPC.Viewer.App/ViewModels/Dialogs/CameraEditorViewModel.cs
index 8dde719..92bb3f6 100644
--- a/src/OpenIPC.Viewer.App/ViewModels/Dialogs/CameraEditorViewModel.cs
+++ b/src/OpenIPC.Viewer.App/ViewModels/Dialogs/CameraEditorViewModel.cs
@@ -159,17 +159,43 @@ private void AutoDeriveRtsp()
RtspMainText = $"rtsp://{Host.Trim()}/";
}
- // XM/Xiongmai (NETSurveillance) firmware embeds the login in the RTSP path
- // and serves main/sub as stream=0/1. Uses the credential fields when set,
- // falling back to the stock "admin" + empty password those cameras ship with.
+ // Vendor RTSP URI templates (camera-editor "Templates" flyout). Fills both
+ // main/sub from the host field. Credentials ride the RTSP auth handshake
+ // (the Username/Password fields), so they are NOT embedded in the URI —
+ // except XM/Xiongmai (NETSurveillance), whose firmware wants the login in
+ // the path itself; there the fields are used, falling back to the stock
+ // "admin" + empty password those cameras ship with.
[RelayCommand]
- private void AutoDeriveXmRtsp()
+ private void ApplyRtspTemplate(string vendor)
{
if (string.IsNullOrWhiteSpace(Host)) return;
var host = Host.Trim();
var user = string.IsNullOrWhiteSpace(Username) ? "admin" : Username.Trim();
- RtspMainText = $"rtsp://{host}:554/user={user}&password={Password}&channel=1&stream=0.sdp?real_stream";
- RtspSubText = $"rtsp://{host}:554/user={user}&password={Password}&channel=1&stream=1.sdp?real_stream";
+ (RtspMainText, RtspSubText) = vendor switch
+ {
+ "openipc" => (
+ $"rtsp://{host}:554/stream0",
+ $"rtsp://{host}:554/stream1"),
+ "xm" => (
+ $"rtsp://{host}:554/user={user}&password={Password}&channel=1&stream=0.sdp?real_stream",
+ $"rtsp://{host}:554/user={user}&password={Password}&channel=1&stream=1.sdp?real_stream"),
+ "hikvision" => (
+ $"rtsp://{host}:554/Streaming/Channels/101",
+ $"rtsp://{host}:554/Streaming/Channels/102"),
+ "dahua" => (
+ $"rtsp://{host}:554/cam/realmonitor?channel=1&subtype=0",
+ $"rtsp://{host}:554/cam/realmonitor?channel=1&subtype=1"),
+ "reolink" => (
+ $"rtsp://{host}:554/h264Preview_01_main",
+ $"rtsp://{host}:554/h264Preview_01_sub"),
+ "tplink" => (
+ $"rtsp://{host}:554/stream1",
+ $"rtsp://{host}:554/stream2"),
+ "uniview" => (
+ $"rtsp://{host}:554/media/video1",
+ $"rtsp://{host}:554/media/video2"),
+ _ => (RtspMainText, RtspSubText),
+ };
}
[RelayCommand(CanExecute = nameof(CanTestConnection))]
diff --git a/src/OpenIPC.Viewer.App/Views/Dialogs/CameraEditorContent.axaml b/src/OpenIPC.Viewer.App/Views/Dialogs/CameraEditorContent.axaml
index f6c02c0..6405022 100644
--- a/src/OpenIPC.Viewer.App/Views/Dialogs/CameraEditorContent.axaml
+++ b/src/OpenIPC.Viewer.App/Views/Dialogs/CameraEditorContent.axaml
@@ -53,13 +53,24 @@
Padding="0"
FontSize="{StaticResource FontSizeSm}" />
+ FontSize="{StaticResource FontSizeSm}">
+
+
+
+
+
+
+
+
+
+
+
+