feat(video): 事务化切换与前端统一编排,增强视频输入格式支持

- 后端:切换事务+transition_id,/stream/mode 返回 switching/transition_id 与实际 codec

- 事件:新增 mode_switching/mode_ready,config/webrtc_ready/mode_changed 关联事务

- 编码/格式:扩展 NV21/NV16/NV24/RGB/BGR 输入与转换链路,RKMPP direct input 优化

- 前端:useVideoSession 统一切换,失败回退真实切回 MJPEG,菜单格式同步修复

- 清理:useVideoStream 降级为 MJPEG-only
This commit is contained in:
mofeng-git
2026-01-11 10:41:57 +08:00
parent 9feb74b72c
commit 206594e292
110 changed files with 3955 additions and 2251 deletions

View File

@@ -12,6 +12,13 @@ export interface ConsoleEventHandlers {
onStreamConfigApplied?: (data: { device: string; resolution: [number, number]; fps: number }) => void
onStreamStatsUpdate?: (data: { clients?: number; clients_stat?: Record<string, { fps: number }> }) => void
onStreamModeChanged?: (data: { mode: string; previous_mode: string }) => void
onStreamModeSwitching?: (data: { transition_id: string; to_mode: string; from_mode: string }) => void
onStreamModeReady?: (data: { transition_id: string; mode: string }) => void
onWebRTCReady?: (data: { codec: string; hardware: boolean; transition_id?: string }) => void
onStreamStateChanged?: (data: { state: string; device?: string | null }) => void
onStreamDeviceLost?: (data: { device: string; reason: string }) => void
onStreamReconnecting?: (data: { device: string; attempt: number }) => void
onStreamRecovered?: (data: { device: string }) => void
onDeviceInfo?: (data: any) => void
onAudioStateChanged?: (data: { streaming: boolean; device: string | null }) => void
}
@@ -21,6 +28,7 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
const systemStore = useSystemStore()
const { on, off, connect } = useWebSocket()
const unifiedAudio = getUnifiedAudio()
const noop = () => {}
// HID event handlers
function handleHidStateChanged(_data: unknown) {
@@ -68,6 +76,7 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
description: t('console.deviceLostDesc', { device: data.device, reason: data.reason }),
duration: 5000,
})
handlers.onStreamDeviceLost?.(data)
}
function handleStreamReconnecting(data: { device: string; attempt: number }) {
@@ -77,6 +86,7 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
duration: 3000,
})
}
handlers.onStreamReconnecting?.(data)
}
function handleStreamRecovered(_data: { device: string }) {
@@ -87,6 +97,7 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
description: t('console.deviceRecoveredDesc'),
duration: 3000,
})
handlers.onStreamRecovered?.(_data)
}
function handleStreamStateChanged(data: { state: string }) {
@@ -95,6 +106,11 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
}
}
function handleStreamStateChangedForward(data: { state: string; device?: string | null }) {
handleStreamStateChanged(data)
handlers.onStreamStateChanged?.(data)
}
// Audio device monitoring handlers
function handleAudioDeviceLost(data: { device?: string; reason: string; error_code: string }) {
if (systemStore.audio) {
@@ -183,11 +199,14 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
on('hid.recovered', handleHidRecovered)
// Stream events
on('stream.config_changing', handlers.onStreamConfigChanging || (() => {}))
on('stream.config_applied', handlers.onStreamConfigApplied || (() => {}))
on('stream.stats_update', handlers.onStreamStatsUpdate || (() => {}))
on('stream.mode_changed', handlers.onStreamModeChanged || (() => {}))
on('stream.state_changed', handleStreamStateChanged)
on('stream.config_changing', handlers.onStreamConfigChanging ?? noop)
on('stream.config_applied', handlers.onStreamConfigApplied ?? noop)
on('stream.stats_update', handlers.onStreamStatsUpdate ?? noop)
on('stream.mode_changed', handlers.onStreamModeChanged ?? noop)
on('stream.mode_switching', handlers.onStreamModeSwitching ?? noop)
on('stream.mode_ready', handlers.onStreamModeReady ?? noop)
on('stream.webrtc_ready', handlers.onWebRTCReady ?? noop)
on('stream.state_changed', handleStreamStateChangedForward)
on('stream.device_lost', handleStreamDeviceLost)
on('stream.reconnecting', handleStreamReconnecting)
on('stream.recovered', handleStreamRecovered)
@@ -206,7 +225,7 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
on('msd.recovered', handleMsdRecovered)
// System events
on('system.device_info', handlers.onDeviceInfo || (() => {}))
on('system.device_info', handlers.onDeviceInfo ?? noop)
// Connect WebSocket
connect()
@@ -219,11 +238,14 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
off('hid.reconnecting', handleHidReconnecting)
off('hid.recovered', handleHidRecovered)
off('stream.config_changing', handlers.onStreamConfigChanging || (() => {}))
off('stream.config_applied', handlers.onStreamConfigApplied || (() => {}))
off('stream.stats_update', handlers.onStreamStatsUpdate || (() => {}))
off('stream.mode_changed', handlers.onStreamModeChanged || (() => {}))
off('stream.state_changed', handleStreamStateChanged)
off('stream.config_changing', handlers.onStreamConfigChanging ?? noop)
off('stream.config_applied', handlers.onStreamConfigApplied ?? noop)
off('stream.stats_update', handlers.onStreamStatsUpdate ?? noop)
off('stream.mode_changed', handlers.onStreamModeChanged ?? noop)
off('stream.mode_switching', handlers.onStreamModeSwitching ?? noop)
off('stream.mode_ready', handlers.onStreamModeReady ?? noop)
off('stream.webrtc_ready', handlers.onWebRTCReady ?? noop)
off('stream.state_changed', handleStreamStateChangedForward)
off('stream.device_lost', handleStreamDeviceLost)
off('stream.reconnecting', handleStreamReconnecting)
off('stream.recovered', handleStreamRecovered)
@@ -239,7 +261,7 @@ export function useConsoleEvents(handlers: ConsoleEventHandlers) {
off('msd.error', handleMsdError)
off('msd.recovered', handleMsdRecovered)
off('system.device_info', handlers.onDeviceInfo || (() => {}))
off('system.device_info', handlers.onDeviceInfo ?? noop)
}
return {