feat: 支持 MJPEG 解码与 MSD 目录配置

- FFmpeg/hwcodec 增加 RKMPP MJPEG 解码与 RAM FFI,ARM 构建启用对应解码器
  - 共享视频管线新增 MJPEG 解码路径(RKMPP/TurboJPEG),优化 WebRTC 发送与 MJPEG 去重
  - MSD 配置改为 msd_dir 并自动创建子目录,接口与前端设置同步更新
  - 更新包依赖与版本号
This commit is contained in:
mofeng-git
2026-01-11 16:32:37 +08:00
parent 0f52168e75
commit 01e01430da
30 changed files with 1185 additions and 260 deletions

View File

@@ -1,7 +1,7 @@
{
"name": "web",
"private": true,
"version": "0.0.0",
"version": "0.1.1",
"type": "module",
"scripts": {
"dev": "vite",

View File

@@ -49,8 +49,10 @@ const systemStore = useSystemStore()
const overflowMenuOpen = ref(false)
// MSD is only available when HID backend is not CH9329 (CH9329 is serial-only, no USB gadget)
const hidBackend = computed(() => (systemStore.hid?.backend ?? '').toLowerCase())
const isCh9329Backend = computed(() => hidBackend.value.includes('ch9329'))
const showMsd = computed(() => {
return props.isAdmin && systemStore.hid?.backend !== 'ch9329'
return props.isAdmin && !isCh9329Backend.value
})
const props = defineProps<{
@@ -310,5 +312,5 @@ const extensionOpen = ref(false)
</div>
<!-- MSD Dialog -->
<MsdDialog v-model:open="msdDialogOpen" />
<MsdDialog v-if="showMsd" v-model:open="msdDialogOpen" />
</template>

View File

@@ -114,6 +114,7 @@ function detectBrowserCodecSupport() {
// Check if a codec is supported by browser
const isBrowserSupported = (codecId: string): boolean => {
if (codecId === 'mjpeg') return true
return browserSupportedCodecs.value.has(codecId)
}
@@ -704,7 +705,7 @@ watch(currentConfig, () => {
v-for="format in availableFormats"
:key="format.format"
:value="format.format"
:class="['text-xs', { 'opacity-50': isFormatNotRecommended(format.format) }]"
class="text-xs"
>
<div class="flex items-center gap-2">
<span>{{ format.description }}</span>

View File

@@ -502,6 +502,11 @@ export default {
notAvailable: 'Not available',
msdEnable: 'Enable MSD',
msdEnableDesc: 'Enable to mount ISO images and virtual drives to the target machine',
msdCh9329Warning: 'HID backend is CH9329, MSD is unavailable',
msdCh9329WarningDesc: 'CH9329 is a serial HID backend and does not support USB Gadget MSD',
msdDir: 'MSD directory',
msdDirDesc: 'MSD base directory containing images/ and ventoy/ subfolders',
msdDirHint: 'Changing this rebuilds MSD and updates console capacity stats',
willBeEnabledAfterSave: 'Will be enabled after save',
disabled: 'Disabled',
msdDesc: 'Mass Storage Device allows you to mount ISO images and virtual drives to the target machine. Use the MSD panel on the main page to manage images.',

View File

@@ -502,6 +502,11 @@ export default {
notAvailable: '不可用',
msdEnable: '启用 MSD',
msdEnableDesc: '启用后可以挂载 ISO 镜像和虚拟驱动器到目标机器',
msdCh9329Warning: '当前 HID 后端为 CH9329MSD 功能不可用',
msdCh9329WarningDesc: 'CH9329 为串口 HID 方案,不支持 USB Gadget 的 MSD 功能',
msdDir: 'MSD 目录',
msdDirDesc: 'MSD 根目录,内部包含 images/ 和 ventoy/ 两个子目录',
msdDirHint: '修改后会重建 MSD控制台容量统计以该目录为准',
willBeEnabledAfterSave: '保存后生效',
disabled: '已禁用',
msdDesc: '虚拟存储设备允许您将 ISO 镜像和虚拟驱动器挂载到目标机器。请在主页面的 MSD 面板中管理镜像。',

View File

@@ -76,12 +76,8 @@ export interface HidConfig {
export interface MsdConfig {
/** Enable MSD functionality */
enabled: boolean;
/** Storage path for ISO/IMG images */
images_path: string;
/** Path for Ventoy bootable drive file */
drive_path: string;
/** Ventoy drive size in MB (minimum 1024 MB / 1 GB) */
virtual_drive_size_mb: number;
/** MSD base directory (absolute path) */
msd_dir: string;
}
/** Driver type for ATX key operations */
@@ -511,9 +507,7 @@ export interface HidConfigUpdate {
export interface MsdConfigUpdate {
enabled?: boolean;
images_path?: string;
drive_path?: string;
virtual_drive_size_mb?: number;
msd_dir?: string;
}
export interface RustDeskConfigUpdate {

View File

@@ -233,6 +233,7 @@ const config = ref({
hid_serial_device: '',
hid_serial_baudrate: 9600,
msd_enabled: false,
msd_dir: '',
network_port: 8080,
encoder_backend: 'auto',
// STUN/TURN settings
@@ -297,6 +298,8 @@ const selectedBackendFormats = computed(() => {
return backend?.supported_formats || []
})
const isCh9329Backend = computed(() => config.value.hid_backend === 'ch9329')
// Video selection computed properties
import { watch } from 'vue'
@@ -536,6 +539,7 @@ async function loadConfig() {
hid_serial_device: hid.ch9329_port || '',
hid_serial_baudrate: hid.ch9329_baudrate || 9600,
msd_enabled: msd.enabled || false,
msd_dir: msd.msd_dir || '',
network_port: 8080, // 从旧 API 加载
encoder_backend: stream.encoder || 'auto',
// STUN/TURN settings
@@ -1499,6 +1503,10 @@ onMounted(async () => {
<CardDescription>{{ t('settings.msdDesc') }}</CardDescription>
</CardHeader>
<CardContent class="space-y-4">
<div v-if="isCh9329Backend" class="rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-sm text-amber-900">
<p class="font-medium">{{ t('settings.msdCh9329Warning') }}</p>
<p class="text-xs text-amber-900/80">{{ t('settings.msdCh9329WarningDesc') }}</p>
</div>
<div class="flex items-center justify-between">
<div class="space-y-0.5">
<Label for="msd-enabled">{{ t('settings.msdEnable') }}</Label>
@@ -1506,11 +1514,21 @@ onMounted(async () => {
</div>
<Switch
id="msd-enabled"
:disabled="isCh9329Backend"
:model-value="config.msd_enabled"
@update:model-value="onMsdEnabledChange"
/>
</div>
<Separator />
<div class="space-y-4">
<div class="space-y-2">
<Label for="msd-dir">{{ t('settings.msdDir') }}</Label>
<Input id="msd-dir" v-model="config.msd_dir" placeholder="/etc/one-kvm/msd" :disabled="isCh9329Backend" />
<p class="text-xs text-muted-foreground">{{ t('settings.msdDirDesc') }}</p>
</div>
<p class="text-xs text-muted-foreground">{{ t('settings.msdDirHint') }}</p>
</div>
<Separator />
<div class="flex items-center justify-between">
<div>
<p class="text-sm font-medium">{{ t('settings.msdStatus') }}</p>