8000 GitHub - eisongao/TY-NVR: TY-NVR supports Frigate app
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

eisongao/TY-NVR

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Download on the App Store Download on the Google Play Store

📷 TY-NVR

TY-NVR 是一个使用 Flutter 构建的轻量级 NVR 应用,专为 Frigate 实时视频分析系统打造。
支持多种视频流协议,提供本地与远程访问、事件查看、推送通知等功能。

🎯 目标平台:Android / iOS / Web(部分支持)
🔒 自主部署,隐私友好,无第三方广告


✨ 功能特性 / Features

  • 🔌 集成 Frigate:通过 MQTT / REST API 与 Frigate 实时对接
  • 🖥️ 支持视频播放:支持 HLS / RTSP / MJPEG 等多种流格式
  • 🔔 移动侦测通知:通过 Firebase 或 WebPush 实现事件提醒
  • 🎥 事件回放:查看 Frigate 检测到的历史事件与录像
  • 🧭 自定义摄像头布局:支持网格展示与单页切换
  • 🛠️ 跨平台支持:一套代码运行于 iOS / Android

📦 技术栈 / Tech Stack


🔧 设置历史回放 / Setup Historical Playback

The default Frigate /api/recordings endpoint only returns recordings from the last hour. To retrieve older recordings, add a custom /histories endpoint.

调整 / Modify frigate/api/media.py

Add the following code to frigate/api/media.py to enable the /histories endpoint:

from datetime import datetime, timedelta
from fastapi import APIRouter, Query
from fastapi.responses import JSONResponse
from frigate.models import Recordings

router = APIRouter()

@router.get("/{camera_name}/histories")
def histories(
    camera_name: str,
    date: str = Query(default=None, description="Date in YYYY-MM-DD format, overrides after/before"),
    after: float = Query(default=None, description="Start timestamp (Unix epoch)"),
    before: float = Query(default=None, description="End timestamp (Unix epoch)"),
    require_motion: bool = Query(default=False, description="Filter recordings with motion"),
    require_objects: bool = Query(default=False, description="Filter recordings with detected objects"),
):
    """Retrieve recordings for a camera within a specified time range (non-paginated)."""

    # Validate camera_name
    if not camera_name:
        return JSONResponse(status_code=400, content={"error": "Camera name is required"})

    # Date takes precedence over after/before
    if date:
        try:
            dt = datetime.strptime(date, "%Y-%m-%d")
            after = dt.timestamp()
            before = (dt + timedelta(days=1)).timestamp()
        except ValueError:
            return JSONResponse(status_code=400, content={"error": "Invalid date format, use YYYY-MM-DD"})

    # Default to past 1 hour if no time range provided
    if after is None or before is None:
        now = datetime.now()
        after = (now - timedelta(hours=1)).timestamp() if after is None else after
        before = now.timestamp() if before is None else before

    # Validate timestamps
    if after >= before:
        return JSONResponse(status_code=400, content={"error": "After timestamp must be earlier than before timestamp"})

    # Build query conditions
    where_clause = [
        Recordings.camera == camera_name,
        Recordings.end_time >= after,
        Recordings.start_time <= before,
    ]
    if require_motion:
        where_clause.append(Recordings.motion > 0)
    if require_objects:
        where_clause.append(Recordings.objects > 0)

    try:
        recordings = (
            Recordings.select(
                Recordings.id,
                Recordings.start_time,
                Recordings.end_time,
                Recordings.segment_size,
                Recordings.motion,
                Recordings.objects,
                Recordings.duration,
                Recordings.path,
            )
            .where(*where_clause)
            .order_by(Recordings.start_time)
            .dicts()
        )
        return JSONResponse(content=list(recordings))
    except Exception as e:
        return JSONResponse(status_code=500, content={"error": f"Failed to retrieve recordings: {str(e)}"})

应用更改 / Apply Changes

  1. Open frigate/api/media.py in your Frigate installation.
  2. Add or replace the /histories endpoint with the code above.
  3. Restart the Frigate service:
    docker restart <your_frigate_container_name>

测试端点 / Test the Endpoint

curl "http://<frigate_host>:5000/api/<camera_name>/histories?date=2025-06-05"

🔧 Firebase 云消息传递 (FCM) 设置 / Firebase Cloud Messaging (FCM) Setup

To enable push notifications for motion detection, integrate Firebase Cloud Messaging (FCM) with both the TY-NVR Flutter app and the Frigate backend.

1. 创建 Firebase 项目 / Create a Firebase Project

  1. Go to Firebase Console.
  2. Click Add Project, name it TY-NVR, and complete the setup.
  3. Enable Cloud Messaging (enabled by default).
  4. Add an Android/iOS app with the package name com.app.frigateNvr.

2. 下载服务帐户密钥 / Download Service Account Key

  1. In Firebase Console, navigate to Project SettingsService Accounts.
  2. Click Generate new private key and download the .json file (e.g., ty-nvr-fcm-service-account.json).

3. 在 Frigate 中安装 firebase-admin / Install firebase-admin in Frigate

To persist the firebase-admin installation, modify the Frigate Docker image:

更新 requirements-wheels.txt / Update requirements-wheels.txt

  1. Locate requirements-wheels.txt in your Frigate directory.

  2. Add:

    firebase-admin==6.5.0
    

    Note: Check for the latest version of firebase-admin if 6.5.0 is outdated:

    pip install firebase-admin --upgrade
  3. Rebuild the Docker image:

    cd /path/to/frigate
    docker build -t frigate-custom .
  4. Update docker-compose.yml:

    services:
      frigate:
        image: frigate-custom
        ...
  5. Restart Frigate:

    docker-compose up -d

4. 将 FCM 凭证存储在数据库中 / Store FCM Credentials in Database

Store the Firebase service account key in the Frigate database for persistent access.

安装 SQLite / Install SQLite

# Debian/Ubuntu
sudo apt-get update
sudo apt-get install -y sqlite3

# CentOS/RHEL
sudo yum install -y sqlite

创建 fcmconfig 表 / Create fcmconfig Table

  1. Back up the Frigate database:

    cp /home/frigate/config/frigate.db /home/frigate/config/frigate.db.bak
  2. Open SQLite:

    sqlite3 /home/frigate/config/frigate.db
  3. Create the table:

    CREATE TABLE IF NOT EXISTS fcmconfig (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        project_id VARCHAR(128) NOT NULL UNIQUE,
        project_name VARCHAR(128) NOT NULL UNIQUE DEFAULT 'tynvr-fcm',
        private_key_id VARCHAR(256) NOT NULL,
        private_key TEXT NOT NULL,
        client_email VARCHAR(256) NOT NULL,
        client_id VARCHAR(128) NOT NULL,
        auth_uri VARCHAR(256) NOT NULL,
        token_uri VARCHAR(256) NOT NULL,
        auth_provider_x509_cert_url VARCHAR(256) NOT NULL,
        client_x509_cert_url VARCHAR(256) NOT NULL,
        created_at DATETIME NOT NULL,
        updated_at DATETIME NOT NULL
    );
  4. Insert service account data (replace placeholders with values from ty-nvr-fcm-service-account.json):

    INSERT INTO fcmconfig (
        project_id,
        project_name,
        private_key_id,
        private_key,
        client_email,
        client_id,
        auth_uri,
        token_uri,
        auth_provider_x509_cert_url,
        client_x509_cert_url,
        created_at,
        updated_at
    ) VALUES (
        'your-project-id',
        'tynvr-fcm',
        'your-private-key-id',
        '-----BEGIN PRIVATE KEY-----\n...\n-----END PRIVATE KEY-----\n',
        'your-client-email@your-project.iam.gserviceaccount.com',
        'your-client-id',
        'https://accounts.google.com/o/oauth2/auth',
        'https://oauth2.googleapis.com/token',
        'https://www.googleapis.com/oauth2/v1/certs',
        'https://your-client-x509-cert-url',
        '2025-06-06 14:03:00',
        '2025-06-06 14:03:00'
    );
  5. Verify and exit:

    .tables
    SELECT * FROM fcmconfig;
    .exit

5. Add FCM Model to Frigate

Modify frigate/models.py to include the FCMConfig model.

from peewee import Model, IntegerField, CharField, TextField, DateTimeField
import datetime

class FCMConfig(Model):
    id = IntegerField(primary_key=True)
    project_id = CharField(max_length=128, unique=True, null=False)
    project_name = CharField(max_length=128, unique=True, null=False, default='tynvr-fcm')
    private_key_id = CharField(max_length=256, null=False)
    private_key = TextField(null=False)
    client_email = CharField(max_length=256, null=False)
    client_id = CharField(max_length=128, null=False)
    auth_uri = CharField(max_length=256, null=False)
    token_uri = CharField(max_length=256, null=False)
    auth_provider_x509_cert_url = CharField(max_length=256, null=False)
    client_x509_cert_url = CharField(max_length=256, null=False)
    created_at = DateTimeField(default=datetime.datetime.now, null=False)
    updated_at = DateTimeField(default=datetime.datetime.now, null=False)

应用更改 / Apply Changes

  1. Open frigate/comms/webpush.py.
  2. Replace the Firebase initialization logic with the code above.
  3. Ensure the CONFIG_DIR path matches your Frigate configuration directory (e.g., /config).
  4. Restart Frigate:
    docker restart <your_frigate_container_name>
service_account_path = os.path.join(CONFIG_DIR, "serviceAccountKey.json")
        logger.debug(f"Checking service account path: {service_account_path}")
        if not os.path.exists(service_account_path):
            logger.error(f"Service account key file not found at {service_account_path}")
        else:
            try:
                try:
                    firebase_admin.get_app()
                    logger.debug("Firebase Admin SDK already initialized")
                except ValueError:
                    cred = credentials.Certificate(service_account_path)
                    firebase_admin.initialize_app(cred)
                    logger.info("Firebase Admin SDK initialized successfully")
            except Exception as e:
                logger.error(f"Failed to initialize Firebase Admin SDK: {str(e)}")
# Initialize Firebase Admin SDK
        try:
            # 这里用 project_name="tynvr-fcm"
            fcm_config = FCMConfig.get(FCMConfig.project_name == "tynvr-fcm")
        except DoesNotExist:
            logger.error("没有在数据库中找到 FCMConfig,无法初始化 Firebase Admin SDK")
        else:
            # 把 Peewee model 里的各字段拼成一
746A
 dict
            service_account_dict = {
                "type": "service_account",  # 如果你表里没存这个字段,可以硬编码
                "project_id": fcm_config.project_id,
                "private_key_id": fcm_config.private_key_id,
                "private_key": fcm_config.private_key,
                "client_email": fcm_config.client_email,
                "client_id": fcm_config.client_id,
                "auth_uri": fcm_config.auth_uri,
                "token_uri": fcm_config.token_uri,
                "auth_provider_x509_cert_url": fcm_config.auth_provider_x509_cert_url,
                "client_x509_cert_url": fcm_config.client_x509_cert_url,
                # 如果你表里还存了 "universe_domain" 之类,也可以一并加上
            }
            try:
                # 如果已经初始化过,就不会再初始化
                firebase_admin.get_app()
                logger.debug("Firebase Admin SDK already initialized")
            except ValueError:
                # 直接把 dict 传给 credentials.Certificate
                try:
                    cred = credentials.Certificate(service_account_dict)
                    firebase_admin.initialize_app(cred)
                    logger.info("Firebase Admin SDK initialized successfully (从数据库读取配置)")
                except Exception as e:
                    logger.error(f"Firebase Admin SDK 初始化失败:{e}")

📸 示例截图 / Example Screenshots

Below are screenshots showcasing TY-NVR’s interface:

  • Home Screen:
    TY-NVR Home Screen
  • Live View:
    TY-NVR Live Screen
  • Playback:
    TY-NVR Playback Screen
  • Multi-Camera Display:
    TY-NVR Multi Screen
  • Events:
    TY-NVR Events Screen
  • Files:
    TY-NVR Files Screen
  • Settings:
    TY-NVR Settings Screen

🚀 后续步骤 / Next Steps

  1. Test FCM Notifications:
    • Trigger a motion event in Frigate and verify that a push notification is received on the TY-NVR app.
  2. Verify Historical Playback:
    • Use the /histories endpoint to fetch recordings older than 1 hour and ensure they display in the TY-NVR app.
  3. Monitor Logs:
    • Check Frigate logs for any Firebase initialization errors:
      docker logs <your_frigate_container_name>

For further assistance, refer to the Frigate documentation or Flutter documentation.

About

TY-NVR supports Frigate app

Resources

License

Stars

Watchers

Forks

Packages

No packages published
0