ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用 OpenClaw + 萤石云摄像头实现零成本智能看护:边缘视觉落地解法|TaoToken 统一 Key 接入

用 OpenClaw + 萤石云摄像头实现零成本智能看护:边缘视觉落地解法|TaoToken 统一 Key 接入 1. 从萤石云摄像头到 OpenClaw边缘视觉看护的真实场景家里有萤石云摄像头的朋友大概率都遇到过这个尴尬摄像头装了APP 也下了但除了偶尔翻翻回放它基本就是个摆设。真出事的时候你不可能 24 小时盯着手机屏幕。我家里两台萤石云一台 CP1 云台机放客厅看娃一台 C2C 固定机位在阳台看猫之前一直靠萤石云 APP 的移动侦测推送结果窗帘一飘、电视画面一切手机就震个不停最后干脆把推送关了。这套方案要解决的问题很具体让摄像头自己看懂画面只在真正出现人和猫的时候才通知你其余时间完全静默。核心链路是 OpenClaw 作为调度中枢调用萤石云开放平台的 RTSP 直播流用 ffmpeg 抽帧YOLO 做语义预筛本地多模态模型做场景理解最后通过飞书群回传告警。整套跑在一台 Mac mini 上API 费用为零硬件全是家里已有的。适合谁跟做有萤石云摄像头或任意支持 RTSP 的 IPC、有一台能 24 小时开机的设备Mac mini / NUC / 旧笔记本都行、想跑通边缘视觉闭环但不想买云服务的开发者。如果你只是想接个大模型 API 聊聊天这篇可能不太对路但如果你想真正把摄像头变成会思考的眼睛下面的每一步都可以直接复制。需要提前说清楚能力边界萤石云开放平台提供 Token 管理、设备列表、云台控制、抓拍、直播流地址获取这些标准 HTTPS 接口不需要逆向私有协议。但不同型号能力差异很大云台机支持预置点巡航固定机位只有抓拍和直播流。代码里必须做设备路由否则云台指令发给固定机位会直接报错。2. TaoToken 统一 Key 接入给 OpenClaw 配一个模型入口OpenClaw 本身是个 Agent 调度框架它需要调用大模型来做指令理解和结果汇总。如果你同时用多个模型比如本地 Ollama 跑视觉、云端跑文本推理每个模型一套 Key、一套 Base URL管理起来很乱。TaoToken 的作用就是把这些入口统一成一个 KeyOpenClaw 里只配一次后面切换模型只改 Model ID。先拿 Key。打开 https://taotoken.net/console 注册后进入控制台在 API Keys 页面创建一个新 Key复制保存。这个 Key 后面要填到 OpenClaw 的配置里格式通常是sk-开头的一串字符。拿到 Key 之后OpenClaw 的模型配置有两种写法。如果你用的是 OpenClaw 的 settings 文件一般在~/.openclaw/settings.json或项目根目录的config/settings.json配置片段长这样{ models: { default: { provider: openai-compatible, base_url: https://taotoken.net/api, api_key: sk-你的TaoToken密钥, model_id: claude-sonnet-4-5, timeout: 60 }, vision_local: { provider: ollama, base_url: http://127.0.0.1:11434, model_id: minicpm-v } } }如果你用的是 TOML 格式的配置部分 OpenClaw 版本支持config.toml等价写法是[models.default] provider openai-compatible base_url https://taotoken.net/api api_key sk-你的TaoToken密钥 model_id claude-sonnet-4-5 timeout 60 [models.vision_local] provider ollama base_url http://127.0.0.1:11434 model_id minicpm-v这里有个关键点Base URL 填https://taotoken.net/api不要带多余的路径后缀。Model ID 按你实际要用的模型填TaoToken 支持的模型列表可以在 https://taotoken.net/doc 查到。API Key 建议不要硬编码在配置文件里用环境变量注入更安全export TAOTOKEN_API_KEYsk-你的TaoToken密钥然后在配置里写api_key: ${TAOTOKEN_API_KEY}。OpenClaw 启动时会自动读取环境变量。如果你用的是 Claude Code 或者 Cline 这类工具配置逻辑一样只是入口不同。Claude Code 的配置在~/.claude/settings.jsonCline 在 VS Code 的设置里找 MCP 配置。核心三件套永远是Base URL API Key Model ID。三者缺一请求就会报 401 或者 model not found。配好之后先别急着跑看护脚本用一条最简单的请求验证 Key 是否生效curl -X POST https://taotoken.net/api/v1/chat/completions \ -H Authorization: Bearer sk-你的TaoToken密钥 \ -H Content-Type: application/json \ -d { model: claude-sonnet-4-5, messages: [{role: user, content: 回复 OK}], max_tokens: 10 }预期返回一个 JSONchoices[0].message.content里是 OK。如果返回 401检查 Key 有没有复制完整如果返回 model not found检查 Model ID 拼写。这一步过了说明 TaoToken 入口通了后面 OpenClaw 调用模型就不会卡在认证上。3. 可复制配置萤石云取流参数与 OpenClaw Skill 片段这一节是整篇的核心所有配置都可以直接复制。先解决萤石云取流。萤石云开放平台的直播流地址通过/api/lapp/live/address/get接口获取需要传accessToken、deviceSerial、channelNo、protocol四个参数。protocol 填3拿 RTSP填2拿 HLS。RTSP 延迟低适合本地 ffmpeg 抽帧HLS 兼容性好但延迟高 3-5 秒看护场景不推荐。取流之前先拿 AccessToken。萤石云的 Token 有效期 7 天过期后所有接口静默失败返回错误码 10002 或 10014。最稳的做法是在 API 调用最底层做自动续期而不是靠上层定时刷新。下面这段 Python 是取流和自动续期的核心逻辑import requests, time, os EZVIZ_BASE https://open.ys7.com APP_KEY os.environ[EZVIZ_APP_KEY] APP_SECRET os.environ[EZVIZ_APP_SECRET] _token None _token_expire 0 def get_token(): global _token, _token_expire if _token and time.time() _token_expire - 300: return _token r requests.post(f{EZVIZ_BASE}/api/lapp/token/get, data{ appKey: APP_KEY, appSecret: APP_SECRET }, timeout15).json() if r.get(code) 200: _token r[data][accessToken] _token_expire r[data][expireTime] / 1000 return _token raise RuntimeError(fget_token failed: {r}) def api(endpoint, params): params[accessToken] get_token() r requests.post(f{EZVIZ_BASE}{endpoint}, dataparams, timeout15).json() if r.get(code) 200: return r.get(data, {}) if r.get(code) in (10002, 10014): global _token _token None params[accessToken] get_token() r requests.post(f{EZVIZ_BASE}{endpoint}, dataparams, timeout15).json() if r.get(code) 200: return r.get(data, {}) return None def get_rtsp_url(device_serial, channel1): data api(/api/lapp/live/address/get, { deviceSerial: device_serial, channelNo: channel, protocol: 3, quality: 1 }) return data[url] if data else None拿到 RTSP URL 后用 ffmpeg 抽帧。看护场景不需要高帧率每 2 分钟抓一张就够。抽帧命令ffmpeg -rtsp_transport tcp -i rtsp://... -frames:v 1 -q:v 2 /tmp/frame_$(date %s).jpg-rtsp_transport tcp强制走 TCP避免 UDP 丢包导致花屏。-frames:v 1只抽一帧。-q:v 2控制 JPEG 质量2 是高质量文件大概 200KB 左右喂给 YOLO 足够。接下来是 OpenClaw Skill 的配置。在 OpenClaw 的 Skills 目录下建一个ezviz-monitor文件夹里面放SKILL.md和monitor.py。SKILL.md定义 Skill 的能力和调用方式--- name: ezviz-monitor description: 萤石云摄像头智能看护支持客厅看娃、阳台看猫、定时巡视、告警推送 --- # 萤石云智能看护 ## 能力 - 客厅巡视检测画面中是否有 person有则推送 GIF - 阳台巡视检测画面中是否有 cat 或 dog有则推送 GIF - 实时查询抓拍当前画面并分析 ## 调用 - 客厅巡视python monitor.py --room living --action patrol - 阳台巡视python monitor.py --room balcony --action patrol - 实时查询python monitor.py --room living --action query ## 路由规则 - 客厅摄像头CP1专门看宝宝千万不能用这个摄像头去找猫 - 阳台摄像头C2C专门看猫不要用来找宝宝monitor.py里封装完整链路接收参数 → 取流 → 抽帧 → YOLO 预筛 → 命中则启动 ffmpeg 录制 → VLM 分析 → 生成 GIF → 输出结果。核心的 YOLO 预筛部分from ultralytics import YOLO model YOLO(yolov8s.pt) def yolo_filter(image_path, targets(person,)): results model(image_path, verboseFalse) for r in results: for box in r.boxes: cls_name model.names[int(box.cls)] conf float(box.conf) if cls_name in targets and conf 0.4: return True, cls_name, conf return False, None, 0.0YOLOv8s 模型 21MB在 Mac mini M4 上单帧推理约 36ms。实测下来Nano 版6MB会把穿白色连体衣的宝宝误识别成 teddy bear置信度只有 0.28Small 版置信度 0.86Medium 版 0.89Large 版 0.90。从 Small 到 Large 推理时间翻 4 倍置信度提升在实际系统里毫无意义所以选 Small 是性价比最高的。VLM 分析用本地 Ollama 跑 MiniCPM-VPrompt 模板VLM_PROMPT 你是一个家庭看护助手。请分析这张摄像头画面用 JSON 返回 {has_target: true/false, target: person/cat/none, scene: 简短中文描述, alert: true/false} 只返回 JSON不要其他内容。调用 Ollamacurl -X POST http://127.0.0.1:11434/api/generate \ -d {model:minicpm-v,prompt:...,images:[base64...],format:json,stream:false}MiniCPM-V 在 Mac mini M4 16GB 上冷启动约 21 秒热推理约 5.5 秒。因为 Cron 每 2 分钟触发一次相当于持续保活模型常驻内存实际延迟稳定在 5.5 秒。4. 验证请求与预期输出从抽帧到推理跑通闭环配置写完必须逐步验证。不要一次性跑完整链路出错了不知道哪一环断。按下面的顺序来。第一步验证萤石云 Token 和取流。运行python -c from monitor import get_token, get_rtsp_url print(token:, get_token()[:20], ...) url get_rtsp_url(你的设备序列号) print(rtsp:, url[:60], ...) 预期输出token 打印前 20 位rtsp 打印一个rtsp://...开头的地址。如果 token 报错检查 APP_KEY 和 APP_SECRET如果 rtsp 返回 None检查设备序列号是否正确、设备是否在线。第二步验证 ffmpeg 抽帧。用上一步拿到的 RTSP URLffmpeg -rtsp_transport tcp -i rtsp://... -frames:v 1 -q:v 2 /tmp/test_frame.jpg ls -lh /tmp/test_frame.jpg预期输出/tmp/test_frame.jpg文件存在大小 150-300KB。如果 ffmpeg 报Connection refused或超时检查 RTSP URL 是否过期萤石云直播流地址有效期通常 1 小时重新取流即可。第三步验证 YOLO 预筛。用抽出来的帧跑python -c from monitor import yolo_filter hit, cls, conf yolo_filter(/tmp/test_frame.jpg, targets(person,cat)) print(fhit{hit} class{cls} conf{conf:.2f}) 预期输出如果画面里有人或猫hitTrueclass 是person或catconf 大于 0.4。如果画面是空房间hitFalse。第一次运行会下载 yolov8s.pt约 21MB耐心等几秒。第四步验证 VLM 推理。把帧转 base64 发给 Ollamapython -c import base64, requests, json img base64.b64encode(open(/tmp/test_frame.jpg,rb).read()).decode() r requests.post(http://127.0.0.1:11434/api/generate, json{ model: minicpm-v, prompt: 用JSON返回画面里有没有人{\has_person\: true/false}, images: [img], format: json, stream: False }, timeout120).json() print(r[response]) 预期输出一个 JSON 字符串类似{has_person: true}。第一次调用会加载模型约 21 秒第二次开始 5.5 秒左右。如果返回空字符串检查 Ollama 是否在跑ollama list看模型在不在以及 Prompt 是否要求了format: json。第五步端到端跑一次完整巡视python monitor.py --room living --action patrol预期输出脚本静默执行如果 YOLO 和 VLM 都判定有人会在/tmp生成一个 GIF并打印[ALERT] living room person detected, gif/tmp/xxx.gif。如果没人打印[SILENT_SAFE_STATE]不生成任何文件。第六步验证 OpenClaw 调度。在 OpenClaw 里手动触发 Skillopenclaw skill run ezviz-monitor --args --room living --action patrol预期输出OpenClaw 返回 Skill 执行结果如果检测到目标飞书群会收到一条 GIF 消息。如果没检测到群里静默。整套验证下来从取流到推理的闭环就通了。实测在 Mac mini M4 上单次巡视抽帧 YOLO VLM耗时约 6 秒其中 YOLO 36msVLM 5.5 秒其余是网络和 IO。5. 本篇常见错排查401、local proxy failed、reading choices、OAuth跑这套链路报错基本集中在几个地方。下面按真实报错逐个拆。401 Unauthorized。这个最常见出现在 TaoToken 请求或萤石云请求。如果是 TaoToken 返回 401检查 API Key 是否复制完整、有没有多余空格、Base URL 是不是https://taotoken.net/api不要带/v1后缀OpenClaw 会自动拼。如果是萤石云返回 401检查 AccessToken 是否过期看返回码是不是 10002 或 10014是的话走自动续期逻辑。local proxy failed。这个报错通常出现在 OpenClaw 调用本地 Ollama 时。原因是 OpenClaw 默认走系统代理而 Ollama 在127.0.0.1:11434代理会把本地请求也拦掉。解法是在 OpenClaw 配置里给本地模型加no_proxy{ models: { vision_local: { provider: ollama, base_url: http://127.0.0.1:11434, model_id: minicpm-v, no_proxy: 127.0.0.1,localhost } } }或者在启动 OpenClaw 前export NO_PROXY127.0.0.1,localhost。reading choices 报错。这个出现在解析模型返回时通常是response.choices为空或不存在。原因有两个一是模型返回了错误信息而不是正常 completion比如{error: model not found}二是 Ollama 返回的格式和 OpenAI 兼容格式不一致。解法是先打印原始返回resp requests.post(...).json() print(json.dumps(resp, ensure_asciiFalse, indent2))看choices字段在不在。如果不在检查 Model ID 是否正确、TaoToken 是否支持这个模型。Ollama 的/api/generate返回的是response字段不是choices别混用。OAuth 相关报错。如果你用 Claude Code 接入可能会遇到 OAuth token 过期。Claude Code 的配置在~/.claude/settings.json三件套是{ env: { ANTHROPIC_BASE_URL: https://taotoken.net/api, ANTHROPIC_API_KEY: sk-你的TaoToken密钥, ANTHROPIC_MODEL: claude-sonnet-4-5 } }如果报 OAuth 失败检查ANTHROPIC_BASE_URL有没有写错以及 Key 是不是 TaoToken 的 Key 而不是 Anthropic 官方的。Cline 的 MCP 配置类似在 VS Code 设置里找cline.apiProvider选openai-compatible填 Base URL 和 Key。YOLO 返回空结果。如果yolo_filter一直返回 False先确认图片路径对不对、图片能不能正常打开。然后降低置信度阈值到 0.25 试试。如果还是不行可能是模型文件损坏删掉yolov8s.pt重新下载。VLM 返回空字符串。这个坑我踩过。Qwen3-VL 的 2B 版本在 Ollama 上请求format: json时输出会写进内部 thinking 字段导致 API 返回为空。换 MiniCPM-V 就好了。如果非要用 Qwen 系列去掉format: json让它自由输出然后自己用正则提取 JSON。ffmpeg 录制延迟。如果你发现 GIF 里总是看不到目标检查录制启动时机。正确做法是抓拍的同时就启动 ffmpeg 建连而不是等 YOLO 或 VLM 出结果再录。萤石云 RTSP 建连握手要 2-3 秒等判断完再录目标早走了。6. 语义一致 CTA把闭环跑起来之后整套方案跑通之后日常体验是这样的飞书群里绝大部分时间完全静默宝宝进客厅了来一段 10 秒 GIF然后沉默 1 小时猫去阳台干饭了同样来一段然后沉默。每晚 18:00 一份家庭日报汇总一天的巡视记录。运行成本忽略不计API 费用为零硬件全是家里已有的。如果你要复现建议按这个顺序先用 TaoToken 拿 Key 并验证模型请求通再配萤石云取流和 ffmpeg 抽帧然后单独跑 YOLO 和 VLM最后用 OpenClaw Skill 串起来。每一步都验证通过再往下走不要跳步。TaoToken 的 API Key 在 https://taotoken.net/api-keys 创建接入文档在 https://taotoken.net/doc模型对话调试在 https://taotoken.net/chat。如果你打算长期跑编码类 Agent 或者多模型调度可以看 https://taotoken.net/coding-planClaude Code 接入参考 https://taotoken.net/claudecode-anthropic。最后分享一个实测有效的技巧所有涉及物理设备的项目先写一个终端调试脚本把硬件交互跑通再做正式业务开发。我调萤石云云台预置点时写了个preset_wizard.py用键盘方向键控制摄像头转动按 P 抓拍预览按 S 保存预置点整个体验像终端遥控器。调试时不用反复掏手机开 APP效率高很多。这个习惯在摄像头、机械臂、传感器这类项目里都适用。
返回列表