一个无状态的音游窝人数统计服务。服务在每次 GET /count 时可同时调用阿里云人体计数和 DeepSeek 视觉模型;两种能力可以单独使用,也可以一起使用。
生产环境通过环境变量配置。调试时也可将相同的键放在当前目录的 .env.json5;进程环境变量优先于该文件。完整示例见 .env.json5.example。
至少配置以下一组凭据,否则程序会在启动时报告配置错误并退出:
- DeepSeek:
DEEPSEEK_API_KEY。配置该密钥时还必须配置RHYTHMNEST_ROOMS_JSON;每项包含name、prompt和图片 URL 数组cameras。 - 阿里云人体计数:
ALIBABA_CLOUD_ACCESS_KEY_ID、ALIBABA_CLOUD_ACCESS_KEY_SECRET和ALIBABA_CLOUD_OSS_BUCKET。阿里云官方所称 AccessKey 是前两个值组成的一对凭据,二者必须同时配置;Bucket 必须位于华东 2(上海),用于临时中转快照。配置后还必须提供RHYTHMNEST_BODY_COUNT_TARGETS_JSON,每项包含name和单个url。
上述两个 *_JSON 配置在环境变量中使用 JSON5 字符串,在 .env.json5 中可以直接使用数组。只配置一类凭据时,响应不会显示另一类的标题或结果。
可选项:
| 变量 | 默认值 |
|---|---|
RHYTHMNEST_HOST |
0.0.0.0 |
RHYTHMNEST_PORT |
8000 |
RHYTHMNEST_LOG_LEVEL |
INFO |
RHYTHMNEST_FETCH_TIMEOUT_SECONDS |
30 |
RHYTHMNEST_MODEL_TIMEOUT_SECONDS |
180 |
RHYTHMNEST_HEARTBEAT_INTERVAL_SECONDS |
5 |
RHYTHMNEST_RETRIES |
2 |
RHYTHMNEST_MAX_PARALLEL_ROOMS |
4 |
RHYTHMNEST_BODY_COUNT_TIMEOUT_SECONDS |
30 |
RHYTHMNEST_OSS_SIGNED_URL_EXPIRES_SECONDS |
600 |
DEEPSEEK_BASE_URL |
https://api.deepseek.com |
DEEPSEEK_MODEL |
deepseek-v4-flash-vision-exp |
DEEPSEEK_THINKING |
enabled |
DEEPSEEK_REASONING_EFFORT |
low |
DEEPSEEK_MAX_TOKENS |
16384 |
ALIBABA_CLOUD_FACEBODY_ENDPOINT |
https://facebody.cn-shanghai.aliyuncs.com |
ALIBABA_CLOUD_OSS_ENDPOINT |
https://oss-cn-shanghai.aliyuncs.com |
ALIBABA_CLOUD_OSS_REGION |
cn-shanghai |
每次分析会先对 DeepSeek 与人体计数配置中的所有 URL 做全局去重,每个唯一 URL 只抓取一次。
图片字节会同时复用给引用它的房间和人体计数目标;重复的人体计数 URL 也只调用一次,
结果会复用到各个名称。所有唯一 URL 并发处理,阿里云人体计数和 DeepSeek 整条处理链也会同时启动。
同一房间的多张快照会合并到一次 DeepSeek 请求,不同房间分别请求;大模型请求并发数由
RHYTHMNEST_MAX_PARALLEL_ROOMS 限制。
人体计数会将抓到的图片上传成 rhythmnest-count/ 前缀下的随机私有 OSS Object,
再把短时签名 GET URL 交给 DetectBodyCount。无论上传或计数成功、失败还是任务取消,
程序都会尝试删除对应 Object;成功上传时会携带返回的 versionId 删除精确版本。
AccessKey 对目标 Bucket 至少需要 oss:PutObject、oss:GetObject、oss:DeleteObject 权限;
Bucket 开启版本控制时还需要 oss:DeleteObjectVersion。建议同时配置生命周期规则,自动清理
rhythmnest-count/ 前缀下因断电或进程被强制终止而没来得及删除的兜底对象。
INFO 日志会按房间输出 image_fetch、model_queue、model_call 各阶段的
latency_ms 和当时累计的 total_latency_ms,任务结束时还会输出状态及总延迟。
.env.json5 支持注释、尾随逗号、单引号和未加引号的对象键。它会被 Git 和 Nix 源码过滤器排除,不会进入构建产物。不要把真实密钥写入 .env.json5.example。
nix develop
nix flake check
nix build .#default
nix run .#default设置必填配置并启动后,请求:
curl http://127.0.0.1:8000/count响应类型为 text/plain; charset=utf-8,内容不使用 Markdown:
人体计数:
里屋:2,外屋:4
大模型输出:
里屋:当前约有2人
外屋:当前约有4人
如果客户端或反向代理会因等待期间没有数据而断开,请改用:
curl --no-buffer http://127.0.0.1:8000/count/stream该端点每隔 RHYTHMNEST_HEARTBEAT_INTERVAL_SECONDS 秒发送一个空行作为心跳,
并在分析完成后输出相同的房间结果。由于 HTTP 状态码会在第一条心跳前确定,
流式端点始终返回 200,分析是否成功以正文中是否包含 错误 判断。
快照源只需能被本服务访问,可以是阿里云无法访问的内网 HTTP/HTTPS 地址;不解析 RTSP、HLS、MP4 或 MJPEG 视频流。DeepSeek 支持 JPEG、PNG、GIF 或 WebP;阿里云人体计数目标遵循官方图片限制:JPEG/JPG/BMP/PNG 且不超过 3 MiB。