CheapSecurity – Linux SBC용 경량 자체 호스팅 CCTV

CheapSecurity – Linux SBC용 경량 자체 호스팅 CCTV

개요

결론: CheapSecurity는 Linux 기반 싱글 보드 컴퓨터와 표준 USB 웹캠을 위해 설계된 경량 자체 호스팅 CCTV 솔루션을 제공합니다. 이 프로젝트는 영상을 로컬에 저장하여 프라이버시를 강조하고, 기존 하드웨어를 재사용함으로써 비용 효율성을 높이며, 저전력 장치에서도 효율적으로 동작하는 최소주의 아키텍처를 특징으로 합니다.

프로젝트 철학

결론: 프로젝트는 프라이버시, 비용 효율성, 최소 자원 사용을 우선시합니다.

  • 프라이버시 우선: 모든 영상이 로컬에 저장되어 제3자 클라우드 구독이 필요 없습니다.
  • 비용 효율성: 기존 Linux 보드와 USB 웹캠을 사용하며 지속적인 비용이 없습니다.
  • 미니멀리스트 아키텍처: Raspberry Pi 또는 Orange Pi와 같은 저전력 SBC에 최적화되었습니다.

기능

결론: CheapSecurity는 실시간 MJPEG 스트리밍, 사전‑움직임 버퍼가 있는 움직임 감지, 이메일 및 Telegram 알림, 야간 모드, 녹화 파일 일괄 작업, 연령·크기·비상 저디스크 정리 정책, systemd 자동 시작 템플릿을 포함합니다.

  • 웹 대시보드에서 접근 가능한 실시간 MJPEG 스트림.
  • 프레임 차이를 이용한 움직임 감지.
  • 설정 가능한 사전 움직임 버퍼를 갖춘 자동 녹화.
  • 움직임이 시작될 때 스냅샷을 첨부하는 이메일 알림.
  • Telegram 연동: 움직임 발생 후 자동 비디오 업로드, 봇 명령 /snapshot, /video <seconds>, /help.
  • 야간 모드: 소프트웨어 CLAHE와 밝기/대비 강화.
  • 녹화 파일에 대한 일괄 작업: 전체 선택, Telegram 전송, ZIP으로 다운로드, 삭제.
  • 연령, 전체 크기 및 비상 저디스크 임계값에 따른 저장소 정리.
  • 자동 시작을 위한 systemd 서비스 템플릿.
  • GNU AGPLv3 라이선스.

요구 사항

결론: 소프트웨어는 Python 3.10 이상, V4L2 지원 OpenCV, USB 웹캠(/dev/video0 기본) 및 선택적으로 이메일 알림을 위한 SMTP 자격 증명이나 Telegram 봇 토큰이 필요합니다.

  • Python 3.10 이상
  • V4L2 지원으로 컴파일된 OpenCV (시스템 패키지 또는 pip을 통한 opencv‑python‑headless).
  • /dev/video0 로 노출된 USB 웹캠 (구성 가능).
  • 옵션: 이메일 알림을 위한 SMTP 서버.
  • 옵션: Telegram 알림을 위한 봇 토큰 및 채팅 ID.

빠른 시작

결론: 설정은 OpenCV 확인, 가상 환경 생성, 패키지 설치, config.json 복사·편집, 앱 실행 순으로 진행됩니다.

  1. OpenCV 확인: python3 -c "import cv2; print(cv2.__version__)".
  2. 누락된 경우, 시스템 패키지(ARM에 권장) 또는 pip install opencv‑python‑headless 로 OpenCV를 설치합니다.
  3. 가상 환경을 만들고 활성화합니다:
    • 시스템 OpenCV용: python3 -m venv venv --system-site-packages.
    • pip OpenCV용: python3 -m venv venvpip install opencv‑python‑headless.
  4. 패키지를 설치합니다: pip install -e ..
  5. 웹캠을 확인합니다: v4l2‑ctl --list-devices.
  6. 예시 설정을 복사하고 편집합니다: cp config.json.example config.json 후 카메라 장치, 해상도, fps, SMTP, Telegram 등을 조정합니다.
  7. 애플리케이션을 실행합니다: ./venv/bin/python -m cheapsecurity.app.
  8. http://<device‑ip>:5000 에서 대시보드를 엽니다.

설정

결론: 설정은 config.json을 통해 수행되며, 카메라, 움직임, 녹화, 알림, telegram, 저장소, 웹, 선택적 HTTP 기본 인증 섹션이 포함됩니다.

  • camera: 장치 인덱스, 해상도, fps, 야간 모드 토글 및 파라미터.
  • motion: 임계값, 최소 컨투어 면적, 쿨다운, 다운스케일링 비율.
  • recording: 저장 디렉터리, 최대 클립 길이, 사전 버퍼 초, 코덱(MJPG 또는 mp4v).
  • notifications: SMTP 서버, 인증 정보, 수신자, 제목, 최소 간격.
  • telegram: 봇 토큰, 채팅 ID, 비디오 전송 플래그, 간격, 명령 폴링.
  • storage: 최대 연령(일), 최대 크기(GB), 정리 간격, 시작 시 삭제 옵션, 비상 자유 공간 임계값.
  • web: 호스트, 포트, 스트림 스케일링 비율.
  • web.auth: 사용자명/비밀번호로 기본 인증 활성화.

파일은 .gitignore에 포함되어 있으며 절대로 커밋해서는 안 됩니다.

Telegram 설정

결론: Telegram 알림을 활성화하려면 BotFather를 통해 봇을 만들고, 채팅 ID를 확인한 뒤 config.jsontelegram 섹션을 채워야 합니다.

  1. @BotFather에게 메시지를 보내 /newbot 명령을 실행하고 생성된 봇 토큰을 복사합니다.
  2. 봇과 채팅을 시작하고 아무 메시지나 보낸 뒤 https://api.telegram.org/bot<YOUR_BOT_TOKEN>/getUpdates 를 조회하여 채팅 ID를 찾습니다(chat 객체 안의 "id":<number> 확인). 그룹의 경우 ID는 음수입니다.
  3. config.json에 다음과 같이 설정합니다:
    "telegram": {
      "enabled": true,
      "bot_token": "YOUR_TOKEN",
      "chat_id": "YOUR_CHAT_ID",
      "send_video": true,
      "min_interval_minutes": 5,
      "poll_commands": true
    }
    
  4. 서비스를 재시작합니다(시스템d 사용 시): sudo systemctl restart cheapsecurity@$(whoami).service.

자동 업로드는 각 움직임 클립 후에 발생하며 min_interval_minutes 로 제한됩니다. 봇 명령 /snapshot, /video <seconds>, /help 은 인증된 채팅 ID에서 사용할 수 있습니다.

이메일 알림

결론: 이메일 알림은 SMTP 자격 증명이 필요하며, Gmail 또는 Google Workspace의 경우 앱 비밀번호를 사용해야 합니다.

  1. Google 계정에서 2단계 인증을 활성화합니다.
  2. ‘Mail’ 용 앱 비밀번호를 생성하고 이름을 지정합니다(예: “CheapSecurity”).
  3. config.jsonnotifications 섹션에 다음과 같이 설정합니다:
    "enabled": true,
    "smtp": {
      "server": "smtp.gmail.com",
      "port": 465,
      "username": "you@gmail.com",
      "password": "APP_PASSWORD_WITHOUT_SPACES",
      "use_tls": true
    },
    "from": "you@gmail.com",
    "to": "you@gmail.com",
    "subject": "CheapSecurity motion alert",
    "min_interval_minutes": 5
    
    여러 수신자를 지정하려면 배열을 사용합니다: "to": ["you@gmail.com", "family@example.com" ]. 앱은 설정된 포트에서 암시적 TLS(SMTP_SSL)를 사용합니다.

야간 모드

결론: 야간 모드는 소프트웨어 CLAHE와 밝기/대비 제어를 사용해 저조도 영상을 향상시키지만, 대부분의 USB 웹캠은 V4L2을 통해 게인/노출을 제공하지 않으므로 진정한 야간 시야를 위해서는 IR 감지 하드웨어가 필요합니다.

  • 야간 모드는 CLAHE(소프트웨어)와 밝기·대비 상승을 결합합니다.
  • 카메라가 V4L2을 통해 해당 제어를 지원하면 FPS를 낮추고 게인/ISO를 높이려고 시도합니다.
  • 많은 USB 웹캠이 ISO/게인/노출 제어를 지원하지 않기 때문에 FPS/게인 조정이 무시될 수 있습니다.
  • 진정한 저조도 성능을 위해서는 IR 감지 카메라와 IR 조명기를 함께 사용하는 것이 권장됩니다.
  • 야간 모드는 대시보드에서 토글할 수 있으며 실시간 스트림, 녹화 및 알림 사진에 적용됩니다.

저장소 및 정리

결론: 녹화 파일은 연령 기반, 크기 기반 및 비상 저디스크 정리 정책에 따라 관리됩니다.

  • recordings/ 디렉터리에 파일이 저장됩니다.
  • 주기적인 정리는 max_age_days(기본 3일)보다 오래된 녹화 파일이나 전체 크기가 max_size_gb를 초과할 경우 파일을 삭제합니다.
  • 정리는 cleanup_interval_minutes마다 실행됩니다.
  • delete_old_on_startuptrue이면 앱 시작 시 오래된 녹화 파일이 삭제됩니다.
  • 비상 트리거: 자유 디스크 공간이 emergency_free_space_gb 이하가 되면 새로운 클립을 기록하기 전에 가장 오래된 emergency_delete_count 녹화 파일이 삭제됩니다.

웹 인터페이스

결론: 대시보드는 실시간 MJPEG 스트림, 상태 패널, 기능 토글 및 녹화된 클립에 대한 일괄 작업을 제공합니다.

  • 브라우저에서 실시간 스트림을 볼 수 있습니다.
  • 상태 패널은 해상도, FPS, 녹화 상태 및 움직임 상태를 표시합니다.
  • 토글을 사용해 야간 모드, 이메일 알림, Telegram 업로드 및 HTTP 기본 인증을 켜거나 끌 수 있습니다.
  • 녹화 목록은 각 행에 체크박스와 일괄 옵션을 포함합니다: 전체 선택, Telegram 전송, 선택 항목을 ZIP으로 다운로드, 선택 항목 삭제.

프로덕션 배포

결론: 프로덕션 환경에서는 Gunicorn을 역방향 프록시와 함께 실행하거나 제공된 systemd 템플릿을 사용합니다; Flask 개발 서버를 직접 노출하지 않도록 합니다.

  1. Gunicorn을 설치합니다(pyproject.toml에 이미 명시됨): 활성화된 venv 안에서 pip install -e ..
  2. 서비스 템플릿을 복사합니다: sudo cp cheapsecurity.service /etc/systemd/system/cheapsecurity@.service.
  3. systemd를 재로드하고 현재 사용자에 대해 서비스를 활성화합니다:
    sudo systemctl daemon-reload
    sudo systemctl enable --now cheapsecurity@$(whoami).service
    
  4. 서비스는 Gunicorn을 0.0.0.0:5000에 바인딩하고 워커 1개와 스레드 4개를 사용합니다(카메라는 하나의 프로세스만 열 수 있기 때문에 워커는 하나만 필요합니다).
  5. sudo journalctl -u cheapsecurity@$(whoami).service -f 로 로그를 확인합니다. 로컬 네트워크를 넘어 서비스를 노출할 경우, HTTPS와 인증이 적용된 역방향 프록시를 Gunicorn 앞에 배치합니다.

프로젝트 구조

결론: 레포지토리는 소스 코드, 테스트, 설정 예시, systemd 서비스 파일 및 녹화 파일 디렉터리를 포함한 일반적인 Python 레이아웃을 따릅니다.

CheapSecurity/
├── src/
│   └── cheapsecurity/
│       ├── app.py          # Development launcher
│       ├── cctv.py         # Motion detection, recording, alerts, Telegram bot
│       ├── web.py          # Flask dashboard and APIs
│       ├── wsgi.py         # Production WSGI entry point
│       ├── diagnose.py     # Diagnostic/troubleshooting script
│       ├── templates/      # HTML templates
│       └── static/         # CSS/JS
├── tests/                  # Test suite
├── config.json             # Local settings (git‑ignored)
├── config.json.example     # Example settings template
├── pyproject.toml          # Package metadata and dependencies
├── cheapsecurity.service   # Systemd template
├── LICENSE                 # GNU AGPLv3
└── recordings/             # Saved videos

문제 해결

결론: 녹화 파일이 나타나지 않을 경우, 서비스가 실행 중인지 확인하고 로그를 검사하며 진단 스크립트를 실행하고 움직임 감지 최소 면적을 낮추는 것을 고려합니다.

  1. 서비스 상태 확인: sudo systemctl status cheapsecurity@$(whoami).service.
  2. 로그 확인: sudo journalctl -u cheapsecurity@$(whoami).service -f.
  3. 진단 도구 실행: source venv/bin/activatepython -m cheapsecurity.diagnose.
  4. 움직임이 감지되지 않으면 config.jsonmotion.min_area 값을 낮춰 감도를 높여 보세요.

라이선스

결론: CheapSecurity는 GNU Affero General Public License v3.0 하에 배포됩니다. 전체 텍스트는 LICENSE 파일을 참고하십시오.

커뮤니티 피드백 (Hacker News)

결론: 댓글자들은 Frigate와의 차이점에 대해 질문하고, 단순 프레임 차이 기반 움직임 감지에 대한 우려를 표명했으며, Raspberry Pi 5를 하드웨어로 제안하고 UI의 스크린샷이나 GIF를 요청했습니다.

  • "이것과 Frigate의 차이점은 무엇인가요? 링크를 클릭하기 전에 이것이 하드웨어 솔루션(오픈 부품으로 직접 카메라를 만드는 것)이라고 생각했습니다." – @drnick1
  • "`motion`은 imagemagick과 curl 옆에 '다른 소프트웨어가 기반으로 하는' 명예의 전당에 올라 있습니다." – @serf
  • "이것은 움직임 감지를 어떻게 처리하나요? 사용해 본 사람 있나요? … Tapo는 기본적인 프레임 차이를 사용하고 매우 형편없어요 … 그림자? DING DING DiNG 움직임 감지! … Nest 카메라가 훨씬 좋습니다 …" – @mattlondon
  • "카메라 추천 있나요? 라즈베리 파이 5가 2대 남아있는데 좋은 기반이 될 것 같습니다." – @ibejoeb
  • "항상 궁금한데, 이런 소프트웨어의 제작자가 UI를 보여주는 스크린샷이나 GIF를 추가하지 않는 이유가 뭘까요? 기능 설명에 웹 인터페이스가 언급되어 있습니다." – @npodbielski

요약

CheapSecurity는 Linux 싱글 보드 컴퓨터용 경량 자체 호스팅 CCTV 시스템으로, 실시간 MJPEG 스트리밍, 움직임 감지, 녹화, 그리고 Telegram/이메일 알림을 제공하며 모든 영상 데이터를 로컬에 보관합니다.

Sources