{"id":49351237,"url":"https://github.com/r0n9/camkeep","last_synced_at":"2026-06-26T05:01:24.469Z","repository":{"id":353058290,"uuid":"1217757934","full_name":"r0n9/camkeep","owner":"r0n9","description":"A lightweight, self-hosted Network Video Recorder (NVR) designed for home NAS and edge devices.","archived":false,"fork":false,"pushed_at":"2026-06-24T01:28:11.000Z","size":8913,"stargazers_count":28,"open_issues_count":2,"forks_count":7,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-24T03:08:11.992Z","etag":null,"topics":["docker","ffmpeg","fnos","go2rtc","golang","ip-camera","nas","nvr","rtsp","self-hosted","surveillance"],"latest_commit_sha":null,"homepage":"","language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/r0n9.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":"NOTICE","maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-22T07:30:32.000Z","updated_at":"2026-06-24T01:27:25.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/r0n9/camkeep","commit_stats":null,"previous_names":["r0n9/camkeep"],"tags_count":35,"template":false,"template_full_name":null,"purl":"pkg:github/r0n9/camkeep","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r0n9%2Fcamkeep","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r0n9%2Fcamkeep/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r0n9%2Fcamkeep/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r0n9%2Fcamkeep/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/r0n9","download_url":"https://codeload.github.com/r0n9/camkeep/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/r0n9%2Fcamkeep/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34803678,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-26T02:00:06.560Z","response_time":106,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","ffmpeg","fnos","go2rtc","golang","ip-camera","nas","nvr","rtsp","self-hosted","surveillance"],"created_at":"2026-04-27T10:01:57.779Z","updated_at":"2026-06-26T05:01:24.424Z","avatar_url":"https://github.com/r0n9.png","language":"Go","funding_links":[],"categories":[],"sub_categories":[],"readme":"# \u003cimg src=\"./static/image/camkeep_w80.png\" width=\"42\" align=\"center\" alt=\"CamKeep Logo\" /\u003e CamKeep\n\n[![Repo](https://img.shields.io/badge/Docker-Repo-007EC6?labelColor-555555\u0026color-007EC6\u0026logo=docker\u0026logoColor=fff\u0026style=flat-square)](https://hub.docker.com/r/r0n9/camkeep)\n[![Version](https://img.shields.io/docker/v/r0n9/camkeep/latest?labelColor-555555\u0026color-007EC6\u0026style=flat-square)](https://hub.docker.com/r/r0n9/camkeep)\n[![Size](https://img.shields.io/docker/image-size/r0n9/camkeep/latest?sort=semver\u0026labelColor-555555\u0026color-007EC6\u0026style=flat-square)](https://hub.docker.com/r/r0n9/camkeep)\n[![Pulls](https://img.shields.io/docker/pulls/r0n9/camkeep?labelColor-555555\u0026color-007EC6\u0026style=flat-square)](https://hub.docker.com/r/r0n9/camkeep)\n[![github: AlexxIT/go2rtc](https://img.shields.io/badge/Repo-AlexxIT/go2rtc-slategray?style=flat\u0026logo=github\u0026logoColor=white)](https://github.com/AlexxIT/go2rtc)\n[![github: r0n9/camkeep](https://img.shields.io/badge/Repo-r0n9/camkeep-slategray?style=flat\u0026logo=github\u0026logoColor=white)](https://github.com/r0n9/camkeep)\n\n[简体中文](./README.md) | [English](./README_en.md)\n\n---\n\n**全面兼容 go2rtc 的自托管 NVR，面向家庭 NAS 与边缘设备。**\n\nCamKeep 基于 Go、go2rtc 和 FFmpeg，提供本地优先的视频接入、录制、回放和设备管理能力。它已经不再只是 RTSP 极简录像机，而是一个可以接入 go2rtc 现有流、ONVIF 设备以及其他 go2rtc source 的统一 NVR 网关。\n\n![camkeep](camkeep_console.png)\n\n## 设计初衷与原则\n\nCamKeep 的初衷不是替代大型企业级安防平台，而是为家庭 NAS、低功耗小主机和内网自托管场景提供一套够用、稳定、可控的 NVR。\n\n* **极简**：单容器运行，配置尽量少，常用能力优先在 Web 控制台完成，不把用户拖进复杂的视频工程配置里。\n* **低功耗**：优先复用 go2rtc 流代理，录像默认流拷贝，封面与状态刷新控制频率和并发，尽量适合长期运行在 NAS、软路由、ARM 小主机上。\n* **内网安全**：默认本地优先，不依赖云端，不上传视频和设备信息；建议部署在可信局域网内，必要时通过本地用户鉴权或反向代理访问。\n\n## ✨ 功能亮点\n\n* 🧩 **go2rtc-native 接入**：支持 RTSP、ONVIF、FFmpeg、脚本等 go2rtc 兼容接入源，也可以直接导入已有 go2rtc 流。\n* 🕹️ **ONVIF 控制与事件诊断**：自动识别 ONVIF 控制候选设备，支持 PTZ、变焦、对焦、光圈控制，并可诊断 Event 服务、PullPoint 支持和最近收到的事件。\n* 🖼️ **实时封面**：每个实时节点展示持久化封面；优先使用 go2rtc 截图，失败后回退本地 FFmpeg。\n* 📺 **紧凑实时看板**：实时节点卡片适配桌面和移动端，封面只在可视区域按需加载，后台轻量巡检，减少性能消耗和画面闪烁。\n* 🕓 **24H 时间轴回放**：保留原卡片列表和旧时间轴，同时新增可吸附到播放器下方的 24H 时间轴，支持拖动、滚轮缩放、移动端双指缩放和按时间点播放。\n* 🧰 **Web 配置管理**：单页面配置管理，支持表单/YAML 双模式、摄像头卡片折叠、恢复未保存修改、单个添加、批量添加和从 go2rtc 导入未接管流。\n* 🎥 **完整录像能力**：支持定时录像、手动强制开始/停止、动检录像、延时摄影、TS/MP4 切片、历史回放、下载和删除。\n* 🧠 **事件源可选的动检**：支持本地低分辨率帧差、ONVIF PullPoint，或自动组合两者，用 Time-Shift 缓存生成事件录像。\n* 🧭 **普通录像动检标记**：连续录像时也能叠加活动区间，不影响录像启停，方便在 24H 时间轴上快速定位有人、车或画面变化的片段。\n* 🧹 **自动存储管理**：支持过期清理、过小碎片过滤、每日按小时/连续区间合并录像；残留的普通录像片段会自动修复封装，动检片段也可按需合并。\n* 🔒 **本地用户与权限**：不依赖云端、不强制账号、不上传摄像头数据；支持本地管理员/只读用户、在线会话状态和按摄像头限制普通用户可见范围。\n\n## 接入源说明\n\nCamKeep 直接沿用 go2rtc 的接入能力，不局限于 RTSP 地址。你可以填写 RTSP、ONVIF、FFmpeg 等接入方式，也可以在 Web 配置页扫描并导入已有 go2rtc 流。导入后，go2rtc 继续管理流定义，CamKeep 负责录制、回放、状态展示和设备控制。\n\n## ONVIF 事件与动检标记\n\nONVIF 接入设备在能力探测成功后，CamKeep 会识别 Event 服务和 PullPoint 支持情况。配置页可以展开 ONVIF 事件诊断，查看监听状态、最近事件，并启动 30 秒 PullPoint 测试监听。\n\n动检录像可以选择三种事件来源：\n\n* 本地帧差：低分辨率检测画面变化，适合没有 ONVIF 事件的摄像头。\n* ONVIF PullPoint：直接使用摄像头上报的事件，CPU 占用更低。\n* 自动模式：ONVIF 健康时优先使用摄像头事件，并在事件后短时用帧差跟踪来延长或结束事件窗口；ONVIF 不可用时回退本地帧差。\n\n普通连续录像还可以单独开启动检标记。它不会控制录像开始或停止，只会把活动区间叠加到 24H 时间轴上，方便回看时快速定位变化片段。\n\n在 1 画面实时直播窗口中，ONVIF 设备会显示事件叠层开关。开启后只租用 PullPoint 监听并展示最近事件，鼠标悬停按钮时显示事件列表，不改变录像策略。\n\n## 🚀 快速部署\n\nCamKeep Docker 镜像内置 go2rtc 和 FFmpeg。推荐使用 host 网络，尤其是需要 WebRTC 低延迟直播时。\n\n### 1. 准备目录与可选配置文件\n\n在 NAS 或服务器上创建基础目录，例如 `/vol1/CamKeep`。首次部署时只要准备 `config/` 和 `records/` 目录即可，配置文件不存在时会在首次启动时自动生成默认模板。推荐先启动服务，再在 Web 配置页添加摄像头；完整 YAML 字段见 [配置说明文档](./conf_usage.md)。\n\nWeb 配置页支持表单编辑、批量添加、从 go2rtc 导入、ONVIF 事件诊断和未保存修改恢复：\n\n![CamKeep 摄像头配置页](camkeep_cam_config.png)\n\n如果你想手写一个最小初始配置，只需要先写清楚摄像头 ID、接入源和录制时间即可，其他常用参数可以之后在 Web 页面里调整。\n\n```yaml\ncameras:\n  - id: \"front-door\"\n    stream_url: \"rtsp://admin:password@192.168.1.100:554/stream\"\n    record_time: \"00:00-23:59\"\n```\n\n说明：`records` 目录会保存录像文件，也会保存每个摄像头的最新封面截图。\n\n### 2. 启动服务\n\n登录鉴权由本地用户文件管理。首次启动时可以用下面示例里的管理员密码初始化内置 `admin` 账号；之后账号、密码和权限都在 Web“用户管理”里维护，修改启动环境变量不会覆盖已有密码。\n\n如果没有设置初始管理员密码，且当前没有任何用户，Web 控制台会先以未启用鉴权的状态启动。此时可以在“用户管理”里创建第一个 `admin` 用户，创建后会自动启用登录保护。固定会话密钥和 HTTPS Cookie 可以在高级部署时再按需配置。\n\n#### Docker Run\n\n```bash\ndocker run -d \\\n  --name camkeep \\\n  --restart unless-stopped \\\n  --network host \\\n  --shm-size=512m \\\n  -e TZ=Asia/Shanghai \\\n  -e CAMKEEP_AUTH_PASSWORD=admin \\\n  -v ${PWD}/config:/app/config \\\n  -v ${PWD}/records:/app/records \\\n  ghcr.io/r0n9/camkeep:latest\n```\n\n#### Docker Compose\n\n```yaml\nservices:\n  camkeep:\n    image: ghcr.io/r0n9/camkeep:latest\n    container_name: camkeep\n    restart: unless-stopped\n    network_mode: \"host\" # 推荐 host 网络，否则 WebRTC 可能握手失败\n    shm_size: \"512m\"\n    environment:\n      - TZ=Asia/Shanghai\n      - CAMKEEP_AUTH_PASSWORD=admin\n    volumes:\n      - ./config:/app/config\n      - ./records:/app/records\n#    ports:\n#      - \"9110:9110\"      # CamKeep Web 控制台\n#      - \"1984:1984\"      # go2rtc API / 控制台\n#      - \"8554:8554\"      # go2rtc RTSP 服务\n#      - \"8555:8555/tcp\"  # WebRTC\n#      - \"8555:8555/udp\"\n```\n\n然后执行：\n\n```bash\ndocker-compose up -d\n```\n\n建议保留 `--shm-size=512m` 或 `shm_size: \"512m\"`。CamKeep 的动检录像 Time-Shift 缓存会优先写入容器 `/dev/shm`，Docker 默认通常只有 64MB，高码率或多路动检时可能导致 FFmpeg 写入失败，表现为缓存引擎退出或动检片段过短。512MB 适合一般 1-2 路摄像头；多路或高码率主码流建议调整到 `1g` 或更高。不使用动检录像时可以按需降低或省略。\n\n### 3. 进入控制台\n\n浏览器访问 `http://\u003c你的NAS IP\u003e:9110`。如果通过示例环境变量初始化了管理员账号，使用用户名 `admin` 和设置的密码登录；后续账号、密码和权限在 Web“用户管理”中维护。\n\n## Web 控制台\n\n* **实时节点**：展示封面、在线状态、录制状态、手动录制控制和实时预览入口；ONVIF 直播窗口可开启事件叠层。\n* **历史录像**：按摄像头和日期查看录像，支持卡片列表、传统时间轴和 24H 时间轴回放，24H 时间轴可叠加动检标记。\n* **配置管理**：支持表单编辑和 YAML 编辑，批量添加摄像头，从 go2rtc 扫描并导入未接管流，ONVIF 设备可查看 Event/PullPoint 诊断。\n* **用户管理**：支持本地用户、管理员/只读角色、账号启停、密码重置、在线会话展示，以及普通用户可访问摄像头范围设置。\n* **ONVIF 控制**：对支持的设备显示 PTZ、变焦、对焦、光圈控制和事件测试入口。\n* **版本更新**：启动后异步检查 GitHub Releases，之后按周期缓存刷新；稳定版发现更新时会在版本号旁展示入口。`dev`、`test` 或自定义版本不会被标记为稳定版升级。\n\n## 隐私说明\n\nCamKeep 默认不包含遥测，不上传视频、设备列表或使用行为。版本检查只请求 GitHub Releases 元数据，用于判断是否有新版本。\n\n## 📄 开源协议\n\n本项目基于 **MIT License** 开源。欢迎提交 Issue 和 PR。\n\nThis project uses:\n\n- go2rtc — https://github.com/AlexxIT/go2rtc\n  Licensed under the MIT License.\n\n\u003ca href=\"https://nextlaunch.io/projects/camkeep\" target=\"_blank\" title=\"Featured on Next Launch\"\u003e\n  \u003cimg src=\"https://nextlaunch.io/images/badges/nextlaunch-badge-light.svg\" alt=\"Featured on Next Launch\" style=\"width: 175px; height: auto;\" /\u003e\n\u003c/a\u003e\n\n---\n\n\u003ca href=\"https://www.star-history.com/?repos=r0n9%2Fcamkeep\u0026type=date\u0026legend=top-left\"\u003e\n \u003cpicture\u003e\n   \u003csource media=\"(prefers-color-scheme: dark)\" srcset=\"https://api.star-history.com/chart?repos=r0n9/camkeep\u0026type=date\u0026theme=dark\u0026legend=top-left\" /\u003e\n   \u003csource media=\"(prefers-color-scheme: light)\" srcset=\"https://api.star-history.com/chart?repos=r0n9/camkeep\u0026type=date\u0026legend=top-left\" /\u003e\n   \u003cimg alt=\"Star History Chart\" src=\"https://api.star-history.com/chart?repos=r0n9/camkeep\u0026type=date\u0026legend=top-left\" /\u003e\n \u003c/picture\u003e\n\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr0n9%2Fcamkeep","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fr0n9%2Fcamkeep","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fr0n9%2Fcamkeep/lists"}