Show HN: CheapSecurity – 轻量级自托管CCTV,适用于Linux单板计算机
摘要
CheapSecurity 是一个轻量级、自托管的CCTV解决方案,适用于Linux单板计算机,提供注重隐私的家庭监控,支持运动检测、录像和Telegram提醒,无需云订阅。
查看缓存全文
缓存时间: 2026/07/27 01:41
gmrandazzo/CheapSecurity
源代码:https://github.com/gmrandazzo/CheapSecurity
CheapSecurity
本项目提供了一个轻量级、自托管的 CCTV 解决方案,专为基于 Linux 的单板计算机(SBC)和标准 USB 摄像头设计。通过将所有视频数据完全控制在本地,它提供了一种经济实惠且注重隐私的家庭监控替代方案。
项目理念
- 隐私优先:所有录像存储在本地,无需第三方云订阅,确保您的数据从不离开网络。
- 经济高效:利用现有硬件(如闲置的 Linux 主板和 USB 摄像头)即可构建功能齐全的监控系统,无重复费用。
- 极简架构:软件经过优化,可在低功耗设备上高效运行,即便在入门级硬件上也能保持高性能。
主要特性
- 硬件无关性:与多种标准 USB 摄像头高度兼容。
- 资源高效:专为基于 Linux 的主板(如 Raspberry Pi、Orange Pi 或类似 SBC)优化。
- 数据主权:完全控制存储路径、保留策略和访问方式。
- 简单部署:快速设置,易于维护。
功能
- 实时 MJPEG 流 + 网页仪表板
- 运动检测(帧差分法)
- 自动录像(含运动前缓冲区)
- 邮件提醒:运动开始时附带快照图片
- Telegram 集成:
- 运动录像后自动上传视频
- 机器人命令:
/snapshot、/video <秒数>、/help
- 夜间模式:低光增强(软件 CLAHE + 亮度/对比度增强)
- 录像批量操作:全选、发送到 Telegram、下载 ZIP、删除
- 存储清理:按时间、总大小和紧急低磁盘空间清理
- systemd 自动启动就绪
- 基于 GNU AGPLv3 许可
环境要求
- Python 3.10 或更高版本
- 支持 V4L2 的 OpenCV(请参阅下方安装选项)
- USB 摄像头(默认
/dev/video0) - 可选:Telegram 机器人令牌(用于 Telegram 通知)
- 可选:SMTP 凭据(用于邮件提醒)
快速开始
-
确认 OpenCV 可用:
python3 -c "import cv2; print(cv2.__version__)"如果未安装 OpenCV,您有两种选择:
- 选项 A — 使用系统 OpenCV 包(推荐用于 ARM 主板,如 Odroid XU4,系统包通常针对主板进行了优化)。
- 选项 B — 通过 pip 安装 OpenCV(在 x86/amd64 机器上或没有系统包时更方便)。由于应用不需要图形界面,请使用
opencv-python-headless。
-
创建并激活虚拟环境,然后安装应用:
选项 A:系统 OpenCV(推荐用于 ARM)
这会创建一个可访问系统 site-packages 的 venv,使系统
cv2在 venv 内可用。cd $HOME/CheapSecurity python3 -m venv venv --system-site-packages source venv/bin/activate pip install -e .选项 B:通过 pip 安装全部
如果没有系统 OpenCV 或更倾向自包含的 venv,使用此选项。
cd $HOME/CheapSecurity python3 -m venv venv source venv/bin/activate pip install opencv-python-headless pip install -e .注意: 在某些较旧的 ARM 主板上,pip 的
opencv-python-headlesswheel 可能不可用或速度较慢。如果出现这种情况,请改用发行版包管理器安装 OpenCV 并使用选项 A。 -
查找您的摄像头设备(通常为
/dev/video0):v4l2-ctl --list-devices -
复制
config.json.example为config.json并编辑:cp config.json.example config.json nano config.json- 设置摄像头设备、分辨率和帧率
- 如需邮件提醒,填写 SMTP 凭据
- 如需 Telegram 上传,填写 Telegram 机器人令牌和聊天 ID
安全:
config.json已列入.gitignore,绝不可提交。该文件包含密码和令牌。始终编辑config.json,而非config.json.example。如果添加新设置,请同时更新两个文件以保持示例文件同步。 -
运行应用:
./venv/bin/python -m cheapsecurity.app -
在浏览器中打开仪表板:
http://<主机IP>:5000
配置
编辑 config.json:
| 部分 | 键 | 说明 |
|---|---|---|
camera | device | V4L2 设备索引(0 = /dev/video0) |
camera | width, height, fps | 捕获分辨率与帧率 |
camera | night_mode | 启用低光增强 |
camera | night_mode_fps | 夜间模式目标 FPS(摄像头可能忽略) |
camera | night_mode_gain | 夜间模式目标模拟增益(摄像头可能忽略) |
camera | night_mode_brightness | 夜间模式亮度增强 |
camera | night_mode_contrast | 夜间模式对比度增强 |
motion | threshold | 像素差异阈值(0-255) |
motion | min_area | 触发运动的最小轮廓面积(全分辨率像素) |
motion | cooldown_seconds | 运动停止后继续录制的秒数 |
motion | scale | 运动检测的降采样因子(节省 CPU) |
recording | dir | 视频保存目录 |
recording | max_duration_seconds | 单个片段的最大长度 |
recording | pre_buffer_seconds | 运动前包含到片段中的秒数 |
recording | codec | 首选 FourCC 编解码器(MJPG 低 CPU,mp4v 文件更小) |
notifications | enabled | 运动时发送邮件提醒 |
notifications | smtp | SMTP 服务器、端口、用户名、密码、TLS |
notifications | from, to, subject | 邮件发件人/收件人/主题(多个收件人使用 ["a@...", "b@..."]) |
notifications | min_interval_minutes | 提醒邮件最小间隔时间 |
telegram | enabled | 运动录像后发送视频到 Telegram |
telegram | bot_token, chat_id | Telegram Bot API 令牌和目标聊天 |
telegram | send_video | 是否自动上传视频文件 |
telegram | min_interval_minutes | Telegram 上传最小间隔时间 |
telegram | poll_commands | 启用 /snapshot、/video 和 /help 机器人命令 |
storage | max_age_days | 删除早于该天数的录像(默认 3 天 = 72小时) |
storage | max_size_gb | 如果总大小超过此值,删除最旧文件 |
storage | cleanup_interval_minutes | 存储清理运行间隔 |
storage | delete_old_on_startup | 若为 false,应用重启时保留旧录像 |
storage | emergency_free_space_gb | 若剩余磁盘空间低于此值,在录制新视频前删除旧录像 |
storage | emergency_delete_count | 紧急清理时删除的最旧录像数量 |
web | host, port | 仪表板绑定地址和端口 |
web | stream_scale | 实时流的降采样因子(节省带宽/CPU) |
web.auth | enabled, username, password | 可选的 HTTP 基本认证 |
Telegram 设置
1. 创建机器人
- 打开 Telegram,向 @BotFather (https://t.me/BotFather) 发送消息。
- 发送
/newbot,按提示选择显示名称和用户名。 - 复制 机器人令牌(格式类似
123456789:ABCdefGHIjklMNOpqrsTUVwxyz)。 - 保持令牌机密——任何持有该令牌的人都可以控制您的机器人。
2. 获取您的聊天 ID
- 用新机器人开始私聊,发送任意消息(例如
/start)。 - 在浏览器中打开以下 URL,将
<您的令牌>替换为真实令牌:https://api.telegram.org/bot<您的令牌>/getUpdates - 查找
"chat":{"id":123456789。该数字即为您的 聊天 ID。- 如果
getUpdates为空,请向机器人再发送一条消息后刷新。 - 如果使用群组聊天,先将机器人添加到群组并在群中发送消息;群组的聊天 ID 为负数。
- 如果
- 复制聊天 ID,包括群组的
-号。
3. 配置应用
填写 config.json 中的 telegram 部分:
"telegram": {
"enabled": true,
"bot_token": "123456789:ABCdefGHIjklMNOpqrsTUVwxyz",
"chat_id": "123456789",
"send_video": true,
"min_interval_minutes": 5,
"poll_commands": true
}
然后重启服务:
sudo systemctl restart cheapsecurity@$(whoami).service
自动上传
运动片段保存后,视频会自动上传到您的 Telegram 聊天。上传受 min_interval_minutes 限制速率。
机器人命令
从您配置的聊天发送:
/snapshot— 接收当前摄像头图片/video 10— 录制并发送 10 秒视频(1–60 秒,默认 10)/help— 列出命令 机器人仅响应您配置的chat_id。 运动优先: 如果系统因检测到运动已正在录像,/video请求不会中断它。机器人会回复正在录制运动视频,并将在完成后自动上传。
邮件提醒
在 config.json 中配置 notifications 部分。附件为运动开始时拍摄的图片。提醒受 min_interval_minutes 限制速率。
Gmail / Google Workspace 设置
Google 已不再允许“安全性较低的应用”使用常规 Gmail 密码。您必须创建一个应用密码。
- 在 Google 账户中启用两步验证:
- https://myaccount.google.com/signinoptions/two-step-verification
- 创建应用密码:
- 前往 https://myaccount.google.com/apppasswords
- 选择应用:Mail
- 选择设备:Other (Custom name) — 输入 “CheapSecurity”
- 点击 Generate 并复制 16 位密码(例如
abcd efgh ijkl mnop)。
- 在
config.json中设置:"notifications": { "enabled": true, "smtp": { "server": "smtp.gmail.com", "port": 465, "username": "[email protected]", "password": "abcdefghijklmnop", "use_tls": true }, "from": "[email protected]", "to": "[email protected]", "subject": "CheapSecurity motion alert", "min_interval_minutes": 5 }- 在
password字段中使用应用密码(无空格),而不是您的 Google 账户密码。 - 对于 Google Workspace 账户,用户名通常为完整的电子邮件地址。
- 应用使用隐式 TLS(
SMTP_SSL)在您配置的端口上。Gmail 在 465 端口接受此方式。
- 在
多个收件人
"to": [ "[email protected]", "[email protected]" ]
夜间模式
夜间模式结合了:
- 软件增强(在 L 通道上使用 CLAHE)
- 摄像头亮度/对比度增强
- 尝试降低 FPS 并提高增益/ISO(如果摄像头支持)
可通过仪表板切换。增强效果应用于实时流、录像和提醒图片。
重要: 大多数 USB 摄像头不通过 V4L2 暴露 ISO/增益/曝光控制,因此 FPS/增益调整可能被忽略。真正的夜视需要红外感应摄像头和红外照明灯。
存储与清理
- 录像保存在
recordings/目录中。 - 周期性清理时删除早于
max_age_days的录像(而非启动时,除非delete_old_on_startup为true)。 - 如果剩余磁盘空间低于
emergency_free_space_gb,在开始录制新视频前删除最旧的emergency_delete_count个录像。 - 周期性清理时删除早于
max_age_days或超过max_size_gb的录像。
Web 界面
- 实时流
- 状态面板(分辨率、FPS、录像状态、运动状态)
- 设置开关:夜间模式、邮件通知、Telegram 上传、内置基本认证
- 录像列表(含每行复选框及批量操作):
- 全选
- 发送到 Telegram
- 下载所选(ZIP)
- 删除所选
生产部署
不要将 Flask 开发服务器暴露到公网。请使用 Gunicorn 配合内置认证或您信赖的反向代理。
1. 安装 Gunicorn
它已在 pyproject.toml 中定义:
cd $HOME/CheapSecurity
source venv/bin/activate
pip install -e .
2. 使用 systemd + Gunicorn 运行
从用户 shell 复制服务模板并启用:
sudo cp cheapsecurity.service /etc/systemd/system/[email protected]
sudo systemctl daemon-reload
sudo systemctl enable --now cheapsecurity@$(whoami).service
这会使 Gunicorn 绑定到 0.0.0.0:5000,使用一个工作进程和四个线程,以便仪表板和流直接在您的网络上可访问。仅使用一个工作进程,因为摄像头必须由单个进程打开。
安全: 若要暴露到公网,请在 Gunicorn 前放置一个带有 HTTPS 和认证的反向代理。如果仅限本地访问,请保持内置认证开启。
查看日志:
sudo journalctl -u cheapsecurity@$(whoami).service -f
项目结构
CheapSecurity/
├── src/
│ └── cheapsecurity/ # Python 包
│ ├── app.py # 开发启动器
│ ├── cctv.py # 运动检测、录像、提醒、Telegram 机器人
│ ├── web.py # Flask 仪表板和 API
│ ├── wsgi.py # 生产 WSGI 入口
│ ├── diagnose.py # 诊断/故障排查脚本
│ ├── templates/ # HTML 模板
│ └── static/ # CSS/JS
├── tests/ # 测试套件
├── config.json # 本地设置(已被 gitignore,绝不提交)
├── config.json.example # 示例设置模板(已提交)
├── pyproject.toml # 包元数据和依赖
├── cheapsecurity.service # systemd 模板
├── LICENSE # GNU AGPLv3
└── recordings/ # 保存的视频文件
故障排查
如果录像停止出现:
- 检查服务是否在运行:
sudo systemctl status cheapsecurity@$(whoami).service - 检查日志:
sudo journalctl -u cheapsecurity@$(whoami).service -f - 运行诊断脚本:
source venv/bin/activate python -m cheapsecurity.diagnose - 如果未检测到运动,尝试降低
motion.min_area值。
许可协议
本项目基于 GNU Affero General Public License v3.0 或更高版本(AGPLv3)许可。详见 LICENSE。
相似文章
Show HN:开源私有家庭安防摄像头系统(端到端加密)
Secluso 是一款基于树莓派的开源、端到端加密家庭安防摄像头系统,可在无需云监控的情况下实现远程访问。它支持 5 分钟快速部署和可重现构建。
我用过的最佳免订阅家庭安全摄像头
Wired 评测了最佳免订阅家庭安全摄像头,这些摄像头将录像存储在本地,重点推荐了 Eufy、Synology、TP-Link Tapo 和 Aqara 等注重隐私用户的首选品牌。
Shelly的新款50美元安防摄像头无需订阅即可监控您的家
Shelly宣布推出一款新款50美元安防摄像头,可无需订阅使用,具备本地视频录制和智能家居自动化功能,并提供可选的云服务。
无需摄像头的最佳运动传感器与家庭安全设备
本文评测了不使用摄像头的运动传感器和家庭安全设备,提供了注重隐私的活动检测替代方案。
Defcon 上最酷的反监控工具 [视频]
在 Defcon 大会上,独立黑客们展示了多种经济实惠、开源的工具,用于检测智能摄像头、伪基站等监控技术,让反监控手段变得更易为公众所用。