feat(web): PerceptionDeviceTable 独立摄像头视频/音频开关 - #398
Conversation
|
👋 感谢提交 PR @n0tssss!维护者会尽快 review。 提交前请确认:
|
PR #398: feat(web) PerceptionDeviceTable 独立摄像头视频/音频开关作者: n0tssss
修改方案要解决的问题:上游 #439 把双摄每通道升为独立一等相机后,web 端控制粒度粗、开关全堆在预览卡片上,5+ 路时按钮拥挤、小屏更糟。目标是把「预览」与「控制」分离——上区卡片只放实时画面,下区一张表统管每台相机的「视频感知 / 音频感知」独立开关,且关掉感知不等于断开连接(预览继续可用)。 整体方案(6 条主线)主线 1 — 在原有「连接黑名单」之外,另开视频、音频两个正交黑名单
主线 2 — 把开关下沉到「订不订这路流」,而不是「连不连这台相机」
主线 3 — 请求契约从「一个必填布尔」扩成「三个可选布尔」,service 拆成四路写入
主线 4 — 改完开关立刻重算订阅,不等相机离线重连
主线 5 — 老数据迁移
主线 6 — 前端:卡片只留预览,控制全搬进表格
关键设计原则
测试覆盖
问题🟡 重要(应当修复)
🔵 建议(可选优化)
结论需要修改 — 3 条 🟡:① 迁移函数自称「一次性」但用状态推断代替完成标记,用已文档化的请求( 三条都是「文档 / 一致性」类而非功能性缺陷,改动量都很小(一个 KV 标记 + 三段注释),不涉及重构。per-modality 功能主体设计自洽且已核对通过:请求契约的「omitted = 不改」两层实现(pydantic 由 review-pr skill v1.6 生成 |
d624ebd to
8b639b9
Compare
18d3df4 to
643743e
Compare
|
/review |
Molly-3000
left a comment
There was a problem hiding this comment.
please resolve conflicts
|
hi Molly, 收到,先 rebase。设计上的事我想先聊清楚再动手——否则容易改一半才发现方向不一致。 我这版的设计(背景)我观察你截图里 main 是「上区卡片堆叠按钮 + 下区只列未感知设备」。
三条具体回应Q1: 视频开关是否并排到画面右上角? Q2: 总开关与画面右上角开关是否重复? Q3: 关掉最后一路是否加提示? 下一步rebase 之前我先坦白我这版的几个已知缺口(review-pr 已标过 🔵):
这些不在 PR #398 范围内但和 Molly 你提到的 UX 直接相关。 期待 ack :) |
**重新提交** PR XiaoMi#398 — 之前已 ack Molly 的设计哲学评论 + 补了 5 个 UX 缺口 (mic opt-in / atCapacity / 不可用相机 / 手动刷新 / 关最后一路 toast), 现在 rebase 上游 main(冲突解决策略: 前后端都保留双方,把 v1 / v2 / voice 三套 schema 合并,0 改 product API)。 合并要点: - 后端: CAMERA_BLACK_LIST_KEY (v1) + CAMERA_VIDEO/AUDIO_BLACK_LIST_KEY (v2) + CAMERA_VOICE_ALLOW_LIST_KEY (mic-opt-in) 三 KV 全部保留,语义清晰分层 - toggle_camera 走 v2 路径 (per-modality) + tri-state 校验 (cloud/lan/lens) + v1→v2 兼容迁移 (enable 方向自动从 v1 删该 did) - toggle_camera_voice 独立端点保留 (mic-off 语义) - 前端: PerceptionDeviceTable 不再 hardcode OpenAI wire format, 通过 toggleScopeCameraV2 (per-modality) + voice toggle (mic-off) 双路 - list_cameras_with_state 返 8 字段: cloud_online/lan_reachable/awake/is_online /voice_in_use/connected + v2 video_enabled/audio_enabled (in_use 仍走 select_active 的活跃集判定,与 v1 in_use 口径一致) **测试**: 103/103 miot_filter+cameras 测试过 (前 commit 是 27 fail),其余 backend 测试 67 fail 是 upstream main 预存的 test_task_router_e2e 等, 跟本 PR 无关。 web: 220/220 过 (5 个新回归测试 for gap 1-5)。 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
605c8b7 to
3f3ca6a
Compare
|
我觉得预览和控制分离这个方向是OK的,表格统管控制确实会更清晰。后续开发请rebase到最新的main分支~ |
08009d4 to
78b4838
Compare
|
Rebased 到 upstream/main(包含 #439 双摄多通道全拆架构)并做了以下适配和调整: 核心设计
适配全拆架构的调整
一个问题请教上游 #439 全拆后每通道升为独立一等相机,双摄一台吃掉 2 个 是否考虑进一步精细化控制?例如让用户选择双摄的哪个通道参与感知,而不是两路无差别全开。这样既能节省连接名额,也避免 AI 收到重复画面。如果方向 OK 我可以继续做。 |
|
Rebase 完成,已适配 #439 全拆多通道架构。本轮变更要点: 预览与控制分离:HeroNow 上区只做纯预览(card 无开关),所有控制统一收进新增的 per-modality 感知开关:后端新增 开关自动激活通道:per-modality 开启时自动激活对应相机通道(否则无实时画面),两路全关时自动停用释放连接。三态门和上限检查对 per-modality 路径同样生效。 音频双闸统一: 关于 @Molly-3000 之前提到的双摄精细化控制:目前表格按物理 did 去重(一行一台),per-modality 按整台控制。双摄两路独立投喂 AI 可能冗余的问题,如果方向 OK 我可以继续做——让用户选择启用哪路镜头,而不是无差别全开。另外感谢你每轮 review 的细致建议,帮了不少忙 🙏 我继续看 CI 还有没有问题需要修,有的话补上。 |
acd8b16 to
0009eea
Compare
|
关于 🟡 音频双闸联动:这是有意设计。 这样设计是为了避免普通用户困惑"音频开了但 AI 听不见"——把"让 AI 听这台相机"收敛为单一开关,首次开启有知情确认弹窗。 |
|
/review |

web 端摄像头感知列表重构:每个摄像头支持独立的视频感知和音频感知开关。
背景
之前 web 端只有一个总开关(全部开/全部关)。现在改为 per-camera per-modality 矩阵——每台摄像头可以单独开关视频感知或音频感知,互不影响。全关时预览不受影响。
做了什么
前端:
PerceptionDeviceTable组件:表格 + per-camera video/audio toggle + 测试按钮PerceptionDeviceTable.helpers:纯函数(排序、computeInUse、masterSwitchState)HeroNow:删除旧 CamSwitch,改用新表格toggleScopeCamera(dids[], inUse)→toggleScopeCamera(CameraToggleItem[])后端:
filter.py:video/audio 独立黑名单 + denied_video/audio_camera_didsschema.py:CameraToggleItem 新增 video_enabled/audio_enabledrouter.py:透传三字段到 serviceservice.py:toggle_camera per-modality + 新上限口径 + in_use None 修复database/kv_repo.py:ScopeConfigKeys 新增 video/audio blacklist keycamera_adapter.py:video/audio 订阅门控 + resync_subscriptionsselect_active_camera_dids:去黑名单过滤(toggle 不影响预览)测试:backend 79/79 + perception helpers 27/27 + web 207/207
验证
No valid active sources✅