fix: 修复 MJPEG模式可用但状态显示离线的问题

This commit is contained in:
mofeng-git
2026-04-11 15:11:47 +08:00
parent 3e35181583
commit 2d81a071e5
3 changed files with 41 additions and 1 deletions

1
.gitignore vendored
View File

@@ -42,3 +42,4 @@ CLAUDE.md
secrets.toml
.env
/docs/
web/package-lock.json

View File

@@ -259,6 +259,30 @@ export const useSystemStore = defineStore('system', () => {
}
}
async function fetchStreamState() {
try {
const [status, modeResp] = await Promise.all([
streamApi.status(),
streamApi.getMode().catch(() => ({ mode: 'mjpeg' }))
])
stream.value = {
online: status.state === 'streaming',
active: status.state !== 'uninitialized',
device: status.device,
format: status.format,
resolution: status.resolution,
targetFps: status.target_fps,
clients: status.clients,
streamMode: modeResp.mode || 'mjpeg',
error: status.state === 'error' ? 'Stream error' : null,
}
return status
} catch (e) {
console.error('Failed to fetch stream state:', e)
throw e
}
}
async function fetchAllStates() {
loading.value = true
error.value = null
@@ -266,7 +290,8 @@ export const useSystemStore = defineStore('system', () => {
try {
await Promise.all([
fetchSystemInfo(),
// HID state is updated via WebSocket device_info event
fetchStreamState().catch(() => null),
fetchHidState().catch(() => null),
fetchAtxState().catch(() => null),
fetchMsdState().catch(() => null),
])

View File

@@ -96,6 +96,7 @@ const videoLoading = ref(true)
const videoError = ref(false)
const videoErrorMessage = ref('')
const videoRestarting = ref(false) // Track if video is restarting due to config change
const mjpegFrameReceived = ref(false) // Whether MJPEG stream has received at least one frame
// Video aspect ratio (dynamically updated from actual video dimensions)
// Using string format "width/height" to let browser handle the ratio calculation
@@ -188,6 +189,11 @@ const videoStatus = computed<'connected' | 'connecting' | 'disconnected' | 'erro
if (webrtc.isConnecting.value) return 'connecting'
if (webrtc.isConnected.value) return 'connected'
}
// MJPEG: check if frames have actually arrived (frontend-side detection)
// This is more reliable than relying on stream.online from backend,
// which can be stale due to the debounce delay in device_info broadcaster.
// Also handles browsers that don't fire img.onload for multipart MJPEG streams.
if (videoMode.value === 'mjpeg' && mjpegFrameReceived.value) return 'connected'
if (systemStore.stream?.online) return 'connected'
return 'disconnected'
})
@@ -680,6 +686,7 @@ function handleVideoLoad() {
// MJPEG video frame loaded successfully - update stream online status
// This fixes the timing issue where device_info event may arrive before stream is fully active
if (videoMode.value === 'mjpeg') {
mjpegFrameReceived.value = true
systemStore.setStreamOnline(true)
// Update aspect ratio from MJPEG image dimensions
const img = videoRef.value
@@ -758,6 +765,7 @@ function handleVideoError() {
// Show loading state immediately
videoLoading.value = true
mjpegFrameReceived.value = false
// Auto-retry with exponential backoff (infinite retry, capped delay)
retryCount++
@@ -1062,6 +1070,7 @@ function refreshVideo() {
backendFps.value = 0
videoError.value = false
videoErrorMessage.value = ''
mjpegFrameReceived.value = false
// Update timestamp to force MJPEG reconnection via reactive URL
isRefreshingVideo = true
@@ -2061,6 +2070,11 @@ async function activateConsoleView() {
isConsoleActive.value = true
registerInteractionListeners()
// Ensure HID WebSocket is connected when console becomes active
if (!hidWs.connected.value) {
hidWs.connect().catch(() => {})
}
if (videoMode.value !== 'mjpeg' && webrtc.videoTrack.value) {
await nextTick()
await rebindWebRTCVideo()