适用设备:reCamera Pro(RV1126B / recamera_v2)。
这些示例演示方案商如何在设备上运行自己的进程对接固件的扩展 API:拿摄像头帧、把结果回注到 OSD/RTSP/录像/推送、用结果驱动 GPIO。全部运行在设备上,是方案商进程,不改固件、不重编固件、不刷自编固件。
事实来源(本目录所有 API 签名逐一核实自这两份文件):
- C ABI:
sdk/librecamera_ext/include/recamera_ext.h - Python 封装:
sdk/librecamera_ext/python/recamera_ext/__init__.py - 概念/约束:
docs/guide/README.md(总入口)+ 各分篇
| 目录 | 语言 | 用到的 API | 一句话 |
|---|---|---|---|
01-hello-frame/ |
Python | FrameSource |
拿几帧存成图,最小取帧示例 |
02-inject-result/ |
Python | ResultSink |
注入一个框/分类/跟踪/关键点,出现在 OSD/RTSP/WS |
03-frame-to-inference-to-osd/ |
Python | FrameSource + ResultSink |
完整闭环:取帧 → 自带算法(帧差运动检测)→ 回注 OSD |
04-gpio-trigger/ |
Python | notify WS + gmgr | 结果命中即拉高/拉低引脚(继电器/LED/告警) |
05-cpp-frame/ |
C | rc_ext_frame_* |
C ABI 拿一帧写盘 + 交叉编译 Makefile |
06-probe/ |
Python | ProbeSource |
观测内建推理流水线各级张量/指标(只读) |
07-shared-model/ |
JSON/发布流 | catalog models[] + /putModel |
可用/已实现:共享大模型不打进包,走 models[]+target_path 由浏览器代取下发(活样本 voice-transcribe) |
08-app-with-deps/ |
JSON/skeleton | manifest deps + per-app venv |
skeleton/未实现:app 独有 Python 依赖(如 PyAV)随包分发、装进 per-app venv 的设计示范(见设计文档) |
09-declarative-output/ |
JSON/manifest | manifest capabilities:["output"] + output 块 |
可用/已实现:声明式把结果发到 MQTT/HTTP/UART/WS + HA Discovery,app.py 零输出代码(ConfigurableSink,活样本 yolo-detector) |
10-video-backends/ |
Python | kit FrameSource ABC + GStreamer/FFmpeg/OpenCV |
第三方视频框架旁路拉 RTSP 取帧,与 kit 原生 frames() 对照(取舍:丢 RGA 硬件 letterbox) |
建议阅读顺序:01 → 02 → 03(03 是"方案商自带流水线"的核心示例),04/05/06 按需。
07/08/09 与 01–06 不同层次:01–06 是「设备上跑自己的进程对接扩展 SDK」的运行时示例; 07/08/09 是「应用中心声明 / 上架」角度——app 包怎么声明并分发共享模型(07,已实现)、 per-app 依赖(08,设计中未实现)、声明式结果输出(09,已实现,改 manifest 不写代码)。 09 的事实来源是
kit/adapters/output_sink.py+internal/OUTPUT_SINK_SPEC.md+docs/guide/output-sink.md;07/08 不涉及扩展 SDK 调用,事实来源是market/{catalog/gen_catalog.py,catalog/models.json,appmgr/server.py,appmgr/modelstore.py}与docs/guide/per-app-dependencies.md。
07/08 提到的下发发生在安装前后。安装 / 卸载入口(market/appmgr,CLI 与 HTTP 共用
server.py 同一实现):
| 动作 | CLI | HTTP |
|---|---|---|
| 安装 | python3 -m appmgr install <pkg.tar.gz> |
POST /api/appMgr/install {path: "/userdata/.../x.tar.gz"} |
| 卸载 | python3 -m appmgr uninstall <id> |
POST /api/appMgr/uninstall {id} |
- install 传的是包路径(先
/upload原始 tar.gz 拿到设备路径,再/install), uninstall 传的是 app id。 - 卸载序列:running → 先
stop;是 single-active → 清 active;再删/userdata/local/apps/<id>/(共享模型/userdata/local/models不删,跨 app 资产)。do_uninstall已预留「if present 连带删 per-app venv/userdata/local/venvs/<id>」钩子 (等 08 的deps落地生效)。
上面 01–03 是最小、单文件示例,便于逐行读懂 SDK 调用。如果你要把扩展 API 接进一个完整的多应用框架(而不是单脚本),参考 kit 的 L0 适配层:
kit/adapters/official.py—OfficialFrameSource(frame.sock零拷贝取帧 → 全分辨率 RGB)+OfficialResultSink(按结果类型路由到result-in.sock→ OSD/录像/推送)。实现统一的FrameSource/ResultSink基类,被kit/adapters/registry.py按 socket 探测自动选中——socket 在就用官方 API,不在就回退 RTSP/WS 兜底,9 个 应用一行不改。OfficialResultSink按各应用产出把结果分发到全套send_*通道: 检测框→send_detections、pose 关键点(健身/跌倒/facemesh)→send_keypoints(带真实 17/468 关键点)、人脸属性/表情→send_classification、跟踪→send_tracking、分割 →send_segmentation。重点注释了方案商最容易踩的点:RGA vs OpenCV 预处理开关、 dma-buf 归还、pts_us对齐、source_id、以及各结果字段→SDK 元组的映射。kit/adapters/_rga.py— 可选的 librga(RK 2D 硬件) NV12→RGB ctypes 薄封装,缺库/ABI 不符时优雅降级到 OpenCV。
端侧验证 TODO(设备在用,实机验证待放行):
official.py/_rga.py的 全链路验证依赖设备上装好librecamera_ext.so(新版sdk/) +librga.so+ 含 扩展 API 的固件。本地仅通过 mock 做了接口一致性/结果路由/降级逻辑单测 (kit/adapters/test_official.py,含 detections/keypoints/classification/tracking 五类映射断言)。放行后需在设备上逐一确认:
- keypoints / classification 的 OSD 绘制是否符合预期(关键点连线、属性文字叠加) —— rkipc 对这两类的绘制样式端到端尚未实测;
- 空结果帧是否正确清屏(当前用空
send_detections清屏,跨任务类型清屏行为待确认);_rga.py的rga_buffer_t布局 /RK_FORMAT_*/imcvtcolor_t符号与设备 librga 一致。
以下对所有示例通用(详见 docs/guide/README.md §1.2):
-
固件必须包含扩展 API。 扩展 socket(
/run/recamera/frame.sock、result-in.sock)只在含扩展 API 的 rkipc 固件里存在。原厂 rkipc 没有这些端点,示例会连接失败。判断方法:ls -l /run/recamera/ # 期望看到 frame.sock / result-in.sock(0660 root:root) -
socket 权限(v1 = root-only,共享 root)。 实测 RV1126B 上
/run/recamera/目录为0750 root:root、socket 文件0660,没有recamera-ext组。扩展应用经appmgr serve以 root 启动(麦克风/摄像头//dev/mpi设备节点均 root 属主,非 root 开不了硬件节点),身份区分靠 SO_PEERCRED + appmgr 注册表而非独立 uid/组。直接以 root 跑即可,无需创建或加入任何组。 -
C 客户端 链接
librecamera_ext.so.1(设备上应已随固件安装到/lib或/usr/lib)。 Python 客户端import recamera_ext(ctypes 薄封装,运行时dlopen同一个.so)。Python 端还需:numpy(frame.array依赖)opencv-python(仅frame.to_bgr()需要;示例 03 用;示例 01 默认走无依赖的 PGM 存盘)
-
握手 SDK 内部自动完成。 frame/result/probe/inference-control 四条 socket 连接后都先走 Hello/HelloAck,无需手写 protobuf。
示例都是单文件脚本 / 单个 C 源文件,拷进设备即可。
reCamera Pro(root 用 adb):
# Python 示例
adb push examples/01-hello-frame/hello_frame.py /root/
adb shell 'cd /root && python3 hello_frame.py'
# C 示例(先在开发机交叉编译,见 05-cpp-frame/README.md)
adb push frame_dump /root/
adb shell '/root/frame_dump'或用 scp(若设备开了 SSH):
scp examples/03-frame-to-inference-to-osd/motion_to_osd.py root@<设备IP>:/root/
ssh root@<设备IP> 'python3 /root/motion_to_osd.py'Python 的 recamera_ext 包:把 sdk/librecamera_ext/python/recamera_ext/ 拷到设备上脚本同级目录,或装进 site-packages。
rc_ext_frame_open failed/rc_ext_result_open failed:多半是固件不含扩展 API(/run/recamera/无对应 socket),或权限不足(非 root——socket 是root:rootroot-only)。先ls -l /run/recamera/。librecamera_ext.so.1 not found:.so未随固件安装。设LD_LIBRARY_PATH指向它所在目录,或给FrameSource(lib_path=...)/ResultSink(lib_path=...)传绝对路径。ModuleNotFoundError: numpy:pip install numpy(或设备上用uv/opkg对应包)。- 注入的框不出现在画面:确认用的是
result-in.sock(本套示例)而非 legacy notify;source_id不能是保留字"builtin";发送速率别超过 60 msg/s。