| name | miloco-perception |
| description | 调用摄像头看画面、听现场声音,或回顾近期事件来判断——在干嘛、有什么动静、是否有人说话/吵闹、刚才/最近发生了什么;通过画面核实设备的开关状态(如开着/关着、亮着/灭着),尤其在拿不到设备上报状态时。读不出画面看不见的具体数值(温度、湿度、音量等)。 |
| metadata | {"author":"miloco","version":"2.0","date":"2026-06-13","openclaw":{"requires":{"bins":["miloco-cli"]}}} |
miloco-perception
米家多模态感知 Skill。通过摄像头视听理解(画面 + 声音)与感知日志,回答现场与近期问题。
核心工作流
解析 → 获取摄像头 → 查日志 or 实时查询 → 回复
第一步 · 解析意图
从用户自然语言中提取:
目标区域:
- 具体房间(客厅 / 卧室 / 门口…) → 该房间摄像头
- "全屋 / 家里"或问题本就覆盖全屋 → 全部摄像头
- 没点名房间、也非全屋意图 → 追问哪个房间(避免对所有摄像头空跑 Omni)
感知问题:在做什么 / 有什么动静 / 现在什么情况
时间:问的是"此刻现场"还是"近期";若是近期,把"刚才 / 刚刚 / 最近"换算成最近一段时间窗(如 1h)
第二步 · 获取摄像头
必须先 perceive devices 拿全量感知源,再选 source——不要直接用预注入 catalog 里的摄像头。 catalog 只是高频子集、不保证覆盖全部摄像头,也不带 online 状态;漏摄像头或拿离线源会导致漏查 / 空跑。
miloco-cli perceive devices
按 room 选出目标区域的在线摄像头 did,作为后续 --source。
第三步 · 查日志 / 实时查询
核心原则:能用日志答的,不调实时。
感知问题
│
├─ 近期/事件类("刚才发生了什么" "最近怎么样")
│ → miloco-cli perceive logs --since <时长> --jsonl
│ 已有感知结果缓存,零大模型成本
│
└─ 此刻细节类("现在在做什么" "猫在干嘛" "看看客厅")
→ miloco-cli perceive query --source <did> [--source <did>] --query "<问题>"
调用摄像头 + Omni API,1-5s,有成本
查询感知日志(零成本,优先使用):
miloco-cli perceive logs --since 1h --jsonl
实时多模态感知(调用 Omni API,1-5s,有成本):
miloco-cli perceive query --source <did> [--source <did>] --query "<用户问题>"
第四步 · 组合回复
- 单一结果 → 直接转述:实时为 Omni API 返回的描述,单条日志直接复述事件本身
- 多个结果 → 按事件和区域归纳,别逐条复述、不必报每条时间点
示例
此刻·全屋 — "猫在干嘛"
解析:区域=全屋,此刻 → 实时
设备:perceive devices → cam_001(客厅摄像头)、cam_002(卧室摄像头)
执行:$ miloco-cli perceive query --source cam_001 --source cam_002 --query "猫在干嘛"
→ "猫在客厅沙发上睡觉"
回复:"猫在客厅沙发上睡觉"
此刻·指定房间 — "客厅是不是有人在说话"
解析:区域="客厅",此刻 → 实时
设备:perceive devices → cam_001(客厅摄像头)、cam_002(卧室摄像头)→ 按 room 选客厅,取 cam_001
执行:$ miloco-cli perceive query --source cam_001 --query "有没有人在说话,在聊什么"
→ "有两个人在聊天,像是在商量晚饭吃什么"
回复:"客厅有两个人在聊天,好像在商量晚饭"
近期回顾 — "门口刚才有什么动静"
解析:区域="门口",近期 → 日志
执行:$ miloco-cli perceive logs --since 1h --jsonl # 最近一段窗口 + 结构化输出,不碰 cursor
→ 2026-06-11T20:35:00+08:00: {"门口": "有人在门口停留"}
2026-06-11T20:52:00+08:00: {"客厅": "客厅有人走动"}
2026-06-11T21:08:00+08:00: {"门口": "快递员放下包裹后离开"}
筛门口记录,归纳为一件事
回复:"门口刚才有人停留过,后来快递放下包裹就走了"
异常处理
| 异常 | 处理方式 | 回复 |
|---|
| 摄像头不可用(区域无摄像头 / 离线) | 有近期感知日志则读取日志,否则如实告知原因 | "客厅没有摄像头" / "摄像头离线,仅能看最近记录" |
| perceive query 超时或返回空 | 退回最近感知日志 | "实时感知失败,最近一次:…" |
| 近期无感知日志 | 能现场判断的问题 → 转 perceive query 实时查看;仅当用户明确问历史 → 才告知无记录 | "实时看了下:客厅没人" / "最近没有感知记录" |
关键规则
- 近期/事件类问题 logs 优先。 回顾类问题先查
perceive logs,有缓存就别调实时;"此刻在干嘛"等当下问题仍走 query,不拿过期缓存充数。
- 查近期事件用
perceive logs --since <窗口>。 取最近一段窗口、不动共享 cursor;--jsonl 仅是结构化输出格式。别裸调 perceive logs(无 --since)——那是游标增量模式,只返回"自上次以来的新事件"并推进共享 cursor,是给持续消费整条流的 agent(如 digest)用的。
- query
code=0 ≠ 成功。 answer 仍可能为空,按失败处理、退回 logs,别把空结果当答案回给用户。
- 设备信息动态获取。 从
perceive devices 拿摄像头,不硬编码设备清单。
- 回复简短自然。 按第四步组合,不堆砌术语或原始字段。
- 隐私保护。 摄像头感知结果不存储原始画面/录音,仅返回文本描述。不主动拍摄/录音,仅在用户明确提问时触发。
- 声音关闭的相机听不到它的现场声音。 声音可按相机开关(面板或
scope camera mic-on/mic-off,见 miloco-miot-scope;状态看 scope camera list 的 voice_in_use)——voice_in_use=false 时该相机音频完全不被处理,perceive query 也听不到它的现场声音(问"有没有人说话"只能靠画面判断);视频感知照常。查询时如实告知「该摄像头声音已关闭」;除非用户明确要求打开,不要自行改动。