CamKeep:专为家庭 NAS 与小主机打造的轻量级自建视频监控系统

如今在家里装一两个网络摄像头,几乎成了许多家庭的刚需——有人为了看家防盗,有人为了随时看一眼熟睡的婴儿,还有人为了在上班时抓拍家里宠物的搞笑日常。 市面上的智能摄像头硬件往往几十到一百出头就能买到,性价比看似极高。但真正用上之后,许多人都会遇到几道躲不开的“坎”: 无休止的云存储订阅套路:不买云存储,历史录像就只能看十几秒甚至只有缩略图;如果家里装了三四个摄像头,一年光是交云存会员费就比摄像头本身还要贵。 挥之不去的隐私安全隐忧:家里的客厅、卧室、大门口实时画面,全部通过第三方厂商的云端中转和存储,隔三岔五爆出的“云端漏洞”或“监控泄露”新闻,让人心里总是不踏实。 传统开源 NVR 又重又繁琐:想在自己的 NAS 或软路由上自建 NVR(网络视频录像机)?市面上的传统方案要么配置复杂得像工业视频工程软件,要么对 CPU 和显卡性能要求苛刻,家里几十瓦的小主机跑上去风扇狂转、发热剧增,实在经不起长期 7×24 小时折腾。 正是出于**“想要一个极简、省电、好用且 100% 掌握在自己手中”**的初衷,我打磨了这款轻量级自托管 NVR——CamKeep。 今天这篇文章不聊晦涩的底层音视频编解码算法,就单纯从家庭用户和 HomeLab 爱好者的日常视角,聊聊它是如何帮我们轻松接管家庭安防的。 什么是 CamKeep? 简单来说,CamKeep 是一个专为家庭 NAS、迷你主机和小服务器设计的轻量级自建网络视频录像系统。 它的核心任务非常纯粹: 接入流:把家里各个品牌(海康、大华、TP-Link、各种海思/雄迈方案等)摄像头的视频流统一聚合起来; 录下来:按照你设定的时间规则,安静无感地把视频持久化存到你的 NAS 硬盘上; 查得到:提供一个清爽易用的 Web 网页端,让你随时随地像刷短视频一样顺滑地拖动时间轴回看录像。 它没有庞杂的企业级安防架构,也不强求高昂的硬件配置。只要你的设备支持运行 Docker(无论是群晖、威联通、Unraid、TrueNAS,还是装了 Linux 的小主机、N1 盒子、树莓派),一条命令就能轻松跑起来。 为什么选择 CamKeep?日常使用中的几大亮点 1. 100% 局域网本地优先,彻底告别云端与订阅 CamKeep 在设计之初就确立了**“内网安全、本地优先”**的原则: 零外部依赖:它不需要注册任何外部云端账号,不依赖厂商的云服务中转,更不会向外界上传你的任何视频片段与设备信息; 免订阅费:你的存储空间有多大,录像就能存多久。硬盘满了?系统会自动按设定的天数循环清理最旧的片段,全程全自动; 本地权限可控:系统内置了本地用户与权限管理,可以为家人创建只读账号,甚至单独限制某个账号只能看门口摄像头,兼顾便利与隐私。 2. 极致的低功耗设计,老旧小主机也能轻松常开 对于 24 小时开机的家庭设备,电耗和发热是必须考虑的现实问题。很多传统 NVR 动辄在后台对视频进行二次转码,导致 CPU 占用率居高不下。 CamKeep 深度复用了开源流媒体项目 go2rtc 的流处理能力,录制时默认采用**“直接流拷贝(Stream-Copy)”**技术——摄像头推过来什么格式,系统就原汁原味地分片写入磁盘,CPU 几乎只需要处理基础的 I/O 写入。这意味着即便是在几瓦功耗的软路由、老款 ARM 设备或低配 J4125 / N100 小主机上接入多路 2K/4K 摄像头,CPU 占用通常也仅有个位数,设备完全不会发烫。 ...

2026年10月26日 · 2 分钟 · 226 字 · R0n9

Gitea 自动备份到 MinIO

Gitea 自动备份到 MinIO 方案说明 为了防止服务器故障、磁盘损坏或误操作导致代码仓库丢失,可以将 Gitea 数据目录定时同步到 MinIO 对象存储,实现异地备份。 本方案基于: Gitea MinIO MinIO Client(mc) Linux Crontab 同步方式采用 mc mirror,支持增量同步,仅传输新增或变更文件。 前置条件 0. docker compose 安装 MinIO services: minio-server: # 这里是正确的服务定义位置minio-server: image: quay.io/minio/minio:RELEASE.2025-04-03T14-56-28Z container_name: minio ports: - "9000:9000" # API端口 - "9001:9001" # 控制台端口 volumes: - /vol1/1000/docker/minio/data:/data # 挂载数据目录 environment: MINIO_ROOT_USER: username # 默认管理员用户名 MINIO_ROOT_PASSWORD: password # 默认管理员密码 command: server --console-address ":9001" /data # 指定控制台端口和数据目录 restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"] interval: 30s timeout: 20s retries: 3 1. 安装 MinIO Client curl https://dl.min.io/client/mc/release/linux-amd64/mc \ -o /usr/local/bin/mc chmod +x /usr/local/bin/mc 验证安装: ...

2026年10月23日 · 2 分钟 · 304 字 · R0n9

Docker安装的Mysql数据库定时备份脚本

功能说明: 使用 docker exec 调用 mysqldump,生成 .sql 备份文件; 文件名中包含当前时间,保存在 mysql_backup/ 目录; 自动清理: 删除 超过 7 天的备份文件; 保留每月 1 号的备份文件,不管时间多久。 脚本 mysql_backup.sh #!/bin/bash # ========== 配置 ========== CONTAINER_NAME="mysql" MYSQL_USER="dbuser" MYSQL_PASSWORD="dbpassword" BACKUP_DIR="/home/ubuntu/mysql_backup" # ========== 创建备份目录 ========== mkdir -p "$BACKUP_DIR" # ========== 生成备份文件名 ========== DATE=$(date '+%Y-%m-%d_%H-%M-%S') BACKUP_FILE="${BACKUP_DIR}/backup_${DATE}.sql" # ========== 执行备份 ========== echo "开始备份:$BACKUP_FILE" docker exec "$CONTAINER_NAME" mysqldump -u "$MYSQL_USER" -p"$MYSQL_PASSWORD" --all-databases > "$BACKUP_FILE" # ========== 清理逻辑 ========== echo "清理旧备份..." # 找出所有 .sql 文件 find "$BACKUP_DIR" -type f -name "*.sql" | while read file; do # 提取文件名中的日期 filename=$(basename "$file") date_str=$(echo "$filename" | grep -oP '\d{4}-\d{2}-\d{2}') # 如果提取不到日期,跳过 if [[ -z "$date_str" ]]; then continue fi # 获取今天日期和文件日期的时间戳 file_ts=$(date -d "$date_str" +%s) today_ts=$(date +%s) # 计算文件和今天的天数差 age_days=$(( (today_ts - file_ts) / 86400 )) # 如果超过 7 天且不是每月 1 号 if [[ $age_days -gt 7 ]]; then day_of_month=$(date -d "$date_str" +%d) if [[ "$day_of_month" != "01" ]]; then echo "删除过期备份:$file" rm -f "$file" fi fi done echo "备份完成。" 设置定时任务 设置每天 12:00 和 20:00 备份一次,并将日志写入文件。 ...

2025年8月20日 · 1 分钟 · 167 字 · R0n9

boardrop.app 网站域名迁移公告

📢 网站域名迁移公告 尊敬的用户朋友们: 为进一步统一品牌形象、提升访问体验,我们的网站已完成域名迁移: 🔗 新域名: https://boardrop.app 🕒 生效时间:即日起 原有域名 https://airclipbd.com 将继续通过 301 重定向自动跳转到新域名,无需用户手动操作。 🌐 为什么更换为 boardrop.app? 新域名的含义和愿景: Board + Drop:灵感源自于“画板投放”、“内容投送”之意,寓意我们的平台是一个灵活、即时、沉浸式的“内容投放空间”。 简洁直观:相较旧域名,boardrop.app 更具可读性和可记忆性,方便用户输入与传播。 强调应用属性:.app 域名表明我们是一个工具型产品,为用户提供高效实用的功能服务。 面向未来:更贴合我们打造多人协作、远程共享与互动的长期愿景。 🔄 域名迁移影响说明 项目 说明 原有链接访问 将自动跳转到 boardrop.app,无需手动修改 浏览器书签 建议手动更新为新域名,以提升访问速度 接口/API调用 建议尽快更新为新域名,旧接口将逐步弃用 搜索引擎收录 已配置 301 重定向,权重将自动过渡至新域名 🔐 HTTPS 加密访问 新域名已部署完整 SSL 安全证书,支持 TLS1.3,确保所有用户访问安全可靠。 感谢您的支持与理解! https://boardrop.app 2025 年 7 月

2025年7月8日 · 1 分钟 · 54 字 · R0n9

Airclipbd 隔空剪贴板 v2.4.1-20250611 版本更新

v2.4.1-20250611 版本更新 Airclipbd 隔空剪贴板 迎来了一个新版本,希望大家能够给予支持! Changelog UI 迎来了一个新设计,更加美观。 局域网互传优化,设备的名称、图标Icon、设备类型展示更加清晰美观。 文件、信息互传窗口优化。

2025年6月25日 · 1 分钟 · 10 字 · R0n9

如何在 Quest 3 上安装 Parsec 串流 PC 或 MacOS

如何在 Quest 3 上安装 Parsec 串流 PC 或 MacOS 在这篇博客中,我们将详细介绍如何在 Meta Quest 3 上安装 Parsec 客户端,并通过远程串流连接到你的 PC 或 MacOS 设备。整个过程非常简单,通过在 APKPure 下载 Parsec 的 XAPK 文件,然后使用 SAI(Split APKs Installer)在 Quest 3 上进行安装,我们就能轻松实现远程桌面体验。 第 1 步:下载 Parsec XAPK 文件 访问 APKPure 网站,搜索 Parsec 客户端,选择适合 arm64-v8a 架构的版本。通常,APKPure 会提供一个 XAPK 格式的下载链接。 在我们的示例中,使用了这个链接:下载 Parsec XAPK。 下载完成后,你会得到一个 .xapk 文件,这个文件实际上是一个压缩包,里面包含了多个 APK 文件。 第 2 步:解压 XAPK 文件 将 .xapk 文件的扩展名改为 .zip,然后解压这个文件。 解压后,你会看到两个 APK 文件: tv.parsec.client.apk(主程序) config.arm64_v8a.apk(针对 ARM64 架构的配置 APK) 这些文件必须一起安装,才能确保 Parsec 客户端正常运行。 ...

2025年4月24日 · 1 分钟 · 204 字 · R0n9

iOS swift 开发学习笔记:关于Share Extension遇到的问题记录

Share Extension 分享扩展 在项目中添加新的 Share Extension target NSExtensionActivationRule 扩展的 Info.plist <key>NSExtensionAttributes</key> <dict> <key>NSExtensionActivationRule</key> <dict> <key>NSExtensionActivationSupportsText</key> <true/> <key>NSExtensionActivationSupportsImageWithMaxCount</key> <integer>9</integer> <key>NSExtensionActivationSupportsWebURLWithMaxCount</key> <integer>1</integer> </dict> </dict> Share Extension 分享扩展,分享发布后直接跳转主应用APP class ShareViewController: SLComposeServiceViewController didSelectPost 方法实现,点击默认的发布按钮后的处理 原本打算尝试点击发布后,打开主应用app,这里一直失败。 主应用URL设置,涉及 URL Types in Info.plist,这里不展开。 排除了主应用的URL错误,尝试在safari中输入url,例如”testProject://“,可以打开主应用。 通过URL打开应用代码,直接使用extension的open方法: if let url = URL(string: "testProject://") { print("URL: \(url)") self.extensionContext?.open(url) { success in print("URL \(success ? "opened" : "failed to open")") self.extensionContext?.completeRequest(returningItems: [], completionHandler: nil) } } else { print("URL 格式错误") return } 问题原因: https://stackoverflow.com/questions/24297273/openurl-not-work-in-action-extension ...

2025年2月27日 · 1 分钟 · 179 字 · R0n9

Firewalld防火墙的规则无法控制Docker端口的问题

在 Ubuntu 系统中使用 firewalld 时,默认情况下,firewalld 不会对 Docker 容器的网络流量生效。这是因为 Docker 在启动时会自动创建自己的 iptables 规则来管理网络,绕过了 firewalld 的规则。这种行为可以确保 Docker 容器的网络功能正常,但也会导致 firewalld 的规则无法控制 Docker 端口。 具体原因有以下几点: 1. Docker 使用 iptables Docker 默认会直接操作 iptables 来管理网络连接,而不是通过 firewalld。因此,firewalld 中的规则不会影响 Docker 创建的容器的网络流量。 2. Docker 配置覆盖 firewalld Docker 会修改 iptables 规则,以确保容器能够进行网络连接和端口转发。这些规则可能与 firewalld 的设置发生冲突,导致 firewalld 对 Docker 的流量无效。 解决方案 如果你希望 firewalld 可以控制 Docker 容器的网络流量,可以尝试以下几种方法。 方法 1: 配置 Docker 使用 firewalld 管理规则 可以通过修改 Docker 的配置,禁用 Docker 自己管理 iptables,让 firewalld 接管。 打开 Docker 配置文件(如果文件不存在,可以新建一个): sudo nano /etc/docker/daemon.json 添加以下配置,禁用 Docker 自动修改 iptables: { "iptables": false } 重启 Docker 服务: sudo systemctl restart docker ...

2024年10月10日 · 1 分钟 · 153 字 · R0n9

Airclipbd 隔空剪贴板 v2.3.1-20240926 版本更新

v2.3.1-20240926 版本更新 Changelog 移除了客户端离线时消息的显示。 Removed the display of messages when the client is offline. 修复了部分剪贴板ID异常获取的问题。 Fixed issues with abnormal retrieval of some board IDs. 区分了大屏与小屏的显示适配,突出了点对点传输功能。 Differentiated the display adaptation for large and small screens, highlighting the point-to-point transmission feature. 大屏显示现支持折叠与展开功能。 Large screen display now supports collapse and expand functionality. 大屏展示 小屏展示

2024年9月26日 · 1 分钟 · 51 字 · R0n9

通过expect登录linux, vim行错乱问题解决方案

背景 当使用 expect 登入你的虚拟主机的时候,你会发现使用 vim,会经常出现行错乱的问题。 原因 expect 脚本自动 ssh 登陆,当终端窗口发生变化时,默认 expect 不会将终端窗口大小改变的信号传送到远程的服务器上,因此在使用上会出现很不方便的地方,比如 vim 打开文件时出现串行,要是含有中文的文件可能根本无法编辑。 解决 #!/usr/bin/env expect #trap sigwinch spawned trap { set rows [stty rows] set cols [stty columns] stty rows $rows columns $cols < $spawn_out(slave,name) } WINCH #... 结果你发现完全OK ,不再乱行了

2024年9月3日 · 1 分钟 · 42 字 · R0n9