del: MJPEG /HTTTP 视频模式删除网页连接统计功能

This commit is contained in:
mofeng-git
2026-07-07 22:08:20 +08:00
parent a0ad151fbc
commit 99c051a874
5 changed files with 36 additions and 33 deletions

View File

@@ -66,6 +66,7 @@ const props = defineProps<{
showTerminal?: boolean
showComputerUse?: boolean
}>()
const showStats = computed(() => (props.videoMode ?? 'mjpeg') !== 'mjpeg')
const emit = defineEmits<{
(e: 'toggleFullscreen'): void
@@ -196,6 +197,7 @@ const RIGHT_FIXED_PX = 120
const collapsibleItems = computed(() => {
const items = ITEM_SPECS.slice(3).filter(item => {
if (item.id === 'msd' && !showMsd.value) return false
if (item.id === 'stats' && !showStats.value) return false
if (item.id === 'terminal' && props.showTerminal === false) return false
return true
})
@@ -244,6 +246,12 @@ const isVisible = (id: CollapsibleItem) => visibleSet.value.has(id)
const hasOverflow = computed(() => {
return collapsibleItems.value.some(i => !visibleSet.value.has(i.id))
})
const hasLeftOverflow = computed(() => {
return collapsibleItems.value.some(i => i.side === 'left' && !visibleSet.value.has(i.id))
})
const hasRightOverflow = computed(() => {
return collapsibleItems.value.some(i => i.side === 'right' && !visibleSet.value.has(i.id))
})
</script>
<template>
@@ -469,10 +477,10 @@ const hasOverflow = computed(() => {
{{ t('actionbar.paste') }}
</DropdownMenuItem>
<DropdownMenuSeparator v-if="(!isVisible('msd') || !isVisible('atx') || !isVisible('paste')) && (!isVisible('stats') || (props.showTerminal !== false && !isVisible('terminal')) || !isVisible('settings'))" />
<DropdownMenuSeparator v-if="hasLeftOverflow && hasRightOverflow" />
<!-- Stats -->
<DropdownMenuItem v-if="!isVisible('stats')" @click="openFromOverflow(() => emit('toggleStats'))">
<DropdownMenuItem v-if="showStats && !isVisible('stats')" @click="openFromOverflow(() => emit('toggleStats'))">
<BarChart3 class="h-4 w-4 mr-2" />
{{ t('actionbar.stats') }}
</DropdownMenuItem>

View File

@@ -17,11 +17,6 @@ const { t } = useI18n()
const props = defineProps<{
open: boolean
videoMode: 'mjpeg' | 'h264' | 'h265' | 'vp8' | 'vp9'
// MJPEG stats
mjpegFps?: number
wsLatency?: number
// WebRTC stats
webrtcStats?: WebRTCStats
}>()
@@ -51,9 +46,6 @@ let lastBytesReceived = 0
let lastPacketsLost = 0
let lastTimestamp = 0
// Is WebRTC mode
const isWebRTC = computed(() => props.videoMode !== 'mjpeg')
function formatTime(ts: number): string {
const date = new Date(ts * 1000)
return date.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
@@ -256,14 +248,13 @@ function addDataPoint() {
timestamps.value.shift()
}
if (isWebRTC.value && props.webrtcStats) {
if (props.webrtcStats) {
const jitter = (props.webrtcStats.jitter || 0) * 1000
jitterHistory.value.push(jitter)
const rtt = (props.webrtcStats.roundTripTime || 0) * 1000
delayHistory.value.push(rtt)
// Packet loss delta
const currentLost = props.webrtcStats.packetsLost || 0
const lostDelta = lastPacketsLost > 0 ? Math.max(0, currentLost - lastPacketsLost) : 0
lastPacketsLost = currentLost
@@ -284,11 +275,10 @@ function addDataPoint() {
lastBytesReceived = currentBytes
lastTimestamp = currentTime
} else {
// MJPEG mode
jitterHistory.value.push(0)
delayHistory.value.push(props.wsLatency || 0)
delayHistory.value.push(0)
packetLossHistory.value.push(0)
fpsHistory.value.push(props.mjpegFps || 0)
fpsHistory.value.push(0)
bitrateHistory.value.push(0)
}
@@ -335,7 +325,7 @@ function formatCandidateType(type: string): string {
// Current stats for header display
const currentStats = computed(() => {
if (isWebRTC.value && props.webrtcStats) {
if (props.webrtcStats) {
const lastBitrate = bitrateHistory.value[bitrateHistory.value.length - 1]
const bitrate = lastBitrate !== undefined ? lastBitrate : 0
return {
@@ -356,8 +346,8 @@ const currentStats = computed(() => {
}
return {
jitter: 0,
delay: props.wsLatency || 0,
fps: props.mjpegFps || 0,
delay: 0,
fps: 0,
resolution: '-',
bitrate: '0',
packetsLost: 0,
@@ -422,7 +412,7 @@ onUnmounted(() => {
<div class="flex items-center gap-2">
<SheetTitle class="text-base">{{ t('stats.title') }}</SheetTitle>
<span class="text-xs px-2 py-0.5 rounded bg-slate-100 dark:bg-slate-800 text-muted-foreground">
{{ isWebRTC ? 'WebRTC' : 'MJPEG' }}
WebRTC
</span>
</div>
</SheetHeader>
@@ -438,7 +428,7 @@ onUnmounted(() => {
</div>
<!-- Network Stability (Jitter) -->
<div class="space-y-2" v-if="isWebRTC">
<div class="space-y-2">
<div class="flex items-center justify-between">
<h4 class="text-sm font-medium">{{ t('stats.stability') }}</h4>
</div>
@@ -462,7 +452,7 @@ onUnmounted(() => {
</div>
<!-- Playback Delay -->
<div class="space-y-2" v-if="isWebRTC">
<div class="space-y-2">
<div class="flex items-center justify-between">
<h4 class="text-sm font-medium">{{ t('stats.delay') }}</h4>
<span class="text-xs text-muted-foreground">
@@ -489,7 +479,7 @@ onUnmounted(() => {
</div>
<!-- Packet Loss -->
<div class="space-y-2" v-if="isWebRTC">
<div class="space-y-2">
<div class="flex items-center justify-between">
<h4 class="text-sm font-medium">{{ t('stats.packetLoss') }}</h4>
<span class="text-xs text-muted-foreground">
@@ -543,7 +533,7 @@ onUnmounted(() => {
</div>
<!-- Additional Stats -->
<div class="space-y-3 pt-2 border-t border-slate-200 dark:border-slate-800" v-if="isWebRTC">
<div class="space-y-3 pt-2 border-t border-slate-200 dark:border-slate-800">
<h4 class="text-sm font-medium">{{ t('stats.additional') }}</h4>
<div class="grid grid-cols-2 gap-3">
<div class="rounded-lg bg-slate-50 dark:bg-slate-900/50 p-3">

View File

@@ -1101,8 +1101,6 @@ export default {
},
stats: {
title: 'Connection Stats',
webrtcMode: 'WebRTC Real-time Stats',
mjpegMode: 'MJPEG Real-time Stats',
current: 'Current Status',
video: 'Video',
videoDesc: 'Video stream from server to client.',
@@ -1122,7 +1120,6 @@ export default {
fps: 'FPS',
resolution: 'Resolution',
packetsLost: 'Packets Lost',
wsLatency: 'WS Latency',
connection: 'Connection Info',
connectionType: 'Connection Type',
transport: 'Transport',

View File

@@ -1100,8 +1100,6 @@ export default {
},
stats: {
title: '连接统计',
webrtcMode: 'WebRTC 实时统计',
mjpegMode: 'MJPEG 实时统计',
current: '当前状态',
video: '视频',
videoDesc: '从服务器到客户端的视频流。',
@@ -1121,7 +1119,6 @@ export default {
fps: '帧率',
resolution: '分辨率',
packetsLost: '丢包数',
wsLatency: 'WS 延迟',
connection: '连接信息',
connectionType: '连接类型',
transport: '传输协议',

View File

@@ -171,6 +171,7 @@ function syncMouseModeFromConfig() {
const virtualKeyboardVisible = ref(false)
const virtualKeyboardAttached = ref(true)
const statsSheetOpen = ref(false)
const showConnectionStats = computed(() => videoMode.value !== 'mjpeg')
const virtualKeyboardConsumerEnabled = computed(() => {
const hid = configStore.hid
if (!hid) return true
@@ -207,6 +208,18 @@ const videoStatus = computed<'connected' | 'connecting' | 'disconnected' | 'erro
return 'disconnected'
})
function openStatsSheet() {
if (showConnectionStats.value) {
statsSheetOpen.value = true
}
}
watch(showConnectionStats, (canShow) => {
if (!canShow) {
statsSheetOpen.value = false
}
})
function getResolutionShortName(width: number, height: number): string {
if (height === 2160 || (height === 2160 && width === 4096)) return '4K'
if (height === 1440) return '2K'
@@ -2835,7 +2848,7 @@ onUnmounted(() => {
:show-terminal="showTerminal"
:show-computer-use="showComputerUse"
@toggle-fullscreen="toggleFullscreen"
@toggle-stats="statsSheetOpen = true"
@toggle-stats="openStatsSheet"
@toggle-virtual-keyboard="handleToggleVirtualKeyboard"
@toggle-mouse-mode="handleToggleMouseMode"
@update:video-mode="handleVideoModeChange"
@@ -3086,10 +3099,8 @@ onUnmounted(() => {
:debug-mode="false"
/>
<StatsSheet
v-if="showConnectionStats"
v-model:open="statsSheetOpen"
:video-mode="videoMode"
:mjpeg-fps="backendFps"
:ws-latency="0"
:webrtc-stats="webrtc.stats.value"
/>
<Dialog v-if="showTerminal" v-model:open="showTerminalDialog">