fix: 修复 rtsp 服务连接错误

This commit is contained in:
mofeng-git
2026-02-11 20:00:33 +08:00
parent 934dc48208
commit 3133db9c86
6 changed files with 287 additions and 88 deletions

View File

@@ -17,7 +17,7 @@ import {
SelectTrigger,
SelectValue,
} from '@/components/ui/select'
import { Monitor, RefreshCw, Loader2, Settings, Zap, Scale, Image } from 'lucide-vue-next'
import { Monitor, RefreshCw, Loader2, Settings, Zap, Scale, Image, AlertTriangle } from 'lucide-vue-next'
import HelpTooltip from '@/components/HelpTooltip.vue'
import {
configApi,
@@ -73,6 +73,48 @@ const loadingCodecs = ref(false)
const backends = ref<EncoderBackendInfo[]>([])
const constraints = ref<StreamConstraintsResponse | null>(null)
const currentEncoderBackend = computed(() => configStore.stream?.encoder || 'auto')
const isRtspEnabled = computed(() => {
if (typeof configStore.rtspStatus?.config?.enabled === 'boolean') {
return configStore.rtspStatus.config.enabled
}
return !!configStore.rtspConfig?.enabled
})
const isRustdeskEnabled = computed(() => {
if (typeof configStore.rustdeskStatus?.config?.enabled === 'boolean') {
return configStore.rustdeskStatus.config.enabled
}
return !!configStore.rustdeskConfig?.enabled
})
const isRtspCodecLocked = computed(() => isRtspEnabled.value)
const isRustdeskWebrtcLocked = computed(() => !isRtspEnabled.value && isRustdeskEnabled.value)
const codecLockSources = computed(() => {
if (isRtspCodecLocked.value) {
return isRustdeskEnabled.value ? 'RTSP/RustDesk' : 'RTSP'
}
if (isRustdeskWebrtcLocked.value) return 'RustDesk'
return ''
})
const codecLockMessage = computed(() => {
if (!codecLockSources.value) return ''
return t('actionbar.multiSourceCodecLocked', { sources: codecLockSources.value })
})
const videoParamWarningSources = computed(() => {
if (isRtspEnabled.value && isRustdeskEnabled.value) return 'RTSP/RustDesk'
if (isRtspEnabled.value) return 'RTSP'
if (isRustdeskEnabled.value) return 'RustDesk'
return ''
})
const videoParamWarningMessage = computed(() => {
if (!videoParamWarningSources.value) return ''
return t('actionbar.multiSourceVideoParamsWarning', { sources: videoParamWarningSources.value })
})
const isCodecLocked = computed(() => !!codecLockMessage.value)
const isCodecOptionDisabled = (codecId: string): boolean => {
if (!isBrowserSupported(codecId)) return true
if (isRustdeskWebrtcLocked.value && codecId === 'mjpeg') return true
return false
}
// Browser supported codecs (WebRTC receive capabilities)
const browserSupportedCodecs = ref<Set<string>>(new Set())
@@ -363,6 +405,16 @@ function syncFromCurrentIfChanged() {
function handleVideoModeChange(mode: unknown) {
if (typeof mode !== 'string') return
if (isRtspCodecLocked.value) {
toast.warning(codecLockMessage.value)
return
}
if (isRustdeskWebrtcLocked.value && mode === 'mjpeg') {
toast.warning(codecLockMessage.value)
return
}
if (constraints.value?.allowed_codecs?.length && !constraints.value.allowed_codecs.includes(mode)) {
toast.error(constraints.value.reason || t('actionbar.selectMode'))
return
@@ -500,6 +552,8 @@ watch(() => props.open, (isOpen) => {
Promise.all([
configStore.refreshVideo(),
configStore.refreshStream(),
configStore.refreshRtspStatus(),
configStore.refreshRustdeskStatus(),
]).then(() => {
initializeFromCurrent()
}).catch(() => {
@@ -539,7 +593,7 @@ watch(currentConfig, () => {
<Select
:model-value="props.videoMode"
@update:model-value="handleVideoModeChange"
:disabled="loadingCodecs || availableCodecs.length === 0"
:disabled="loadingCodecs || availableCodecs.length === 0 || isRtspCodecLocked"
>
<SelectTrigger class="h-8 text-xs">
<div v-if="selectedCodecInfo" class="flex items-center gap-1.5 truncate">
@@ -561,8 +615,8 @@ watch(currentConfig, () => {
v-for="codec in availableCodecs"
:key="codec.id"
:value="codec.id"
:disabled="!isBrowserSupported(codec.id)"
:class="['text-xs', { 'opacity-50': !isBrowserSupported(codec.id) }]"
:disabled="isCodecOptionDisabled(codec.id)"
:class="['text-xs', { 'opacity-50': isCodecOptionDisabled(codec.id) }]"
>
<div class="flex items-center gap-2">
<span>{{ codec.name }}</span>
@@ -589,6 +643,9 @@ watch(currentConfig, () => {
<p v-if="props.videoMode !== 'mjpeg'" class="text-xs text-muted-foreground">
{{ t('actionbar.webrtcHint') }}
</p>
<p v-if="isCodecLocked" class="text-xs text-amber-600 dark:text-amber-400">
{{ codecLockMessage }}
</p>
</div>
<!-- Bitrate Preset - Only shown for WebRTC modes -->
@@ -655,6 +712,16 @@ watch(currentConfig, () => {
<Separator />
<div class="space-y-3">
<div
v-if="videoParamWarningMessage"
class="rounded-md border border-amber-500/30 bg-amber-500/10 px-2.5 py-2"
>
<p class="flex items-start gap-1.5 text-xs text-amber-700 dark:text-amber-300">
<AlertTriangle class="h-3.5 w-3.5 mt-0.5 shrink-0" />
<span>{{ videoParamWarningMessage }}</span>
</p>
</div>
<div class="flex items-center justify-between">
<h5 class="text-xs font-medium text-muted-foreground">{{ t('actionbar.deviceSettings') }}</h5>
<Button

View File

@@ -134,6 +134,8 @@ export default {
backendAuto: 'Auto',
recommended: 'Recommended',
notRecommended: 'Not Recommended',
multiSourceCodecLocked: '{sources} are enabled. Current codec is locked.',
multiSourceVideoParamsWarning: '{sources} are enabled. Changing video device and input parameters will interrupt the stream.',
// HID Config
hidConfig: 'Mouse & HID',
mouseSettings: 'Mouse Settings',

View File

@@ -134,6 +134,8 @@ export default {
backendAuto: '自动',
recommended: '推荐',
notRecommended: '不推荐',
multiSourceCodecLocked: '{sources} 已启用,当前编码已锁定',
multiSourceVideoParamsWarning: '{sources} 已启用,修改视频设备和输入参数将导致流中断',
// HID Config
hidConfig: '鼠键配置',
mouseSettings: '鼠标设置',