Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

frigate-gdrive-sync

🇫🇷 Français | 🇬🇧 English


Français

Présentation

frigate-gdrive-sync est un service Docker qui écoute les événements de détection de Frigate NVR via MQTT et sauvegarde automatiquement les clips vidéo, snapshots et métadonnées sur Google Drive via rclone.

Il est conçu pour tourner en colocalisé avec Frigate dans un LXC Proxmox, mais fonctionne aussi depuis n'importe quelle machine du réseau (Mac, autre serveur).

Fonctionnalités

  • Écoute MQTT avec reconnexion automatique
  • Téléchargement des clips (.mp4), snapshots (.jpg) et métadonnées (.json) depuis l'API Frigate
  • Upload via rclone vers Google Drive (ou tout autre remote rclone)
  • Workers parallèles — N caméras traitées simultanément (configurable)
  • Queue persistante SQLite — aucun événement perdu après un redémarrage
  • Retry avec backoff exponentiel — gère les clips pas encore encodés par Frigate
  • Rétention automatique — suppression des fichiers plus vieux que N jours sur Google Drive
  • Arborescence personnalisable via template de chemin ({date}/{camera}, {camera}/{label}, etc.)
  • Fallback d'hôte — détection automatique si Frigate est local ou distant (pratique pour le dev)
  • Health check HTTP sur /health (port 8080)
  • Dry-run — simule les uploads sans rien écrire sur Drive
  • Logs structurés JSON (ou texte coloré pour le dev)

Architecture

Broker MQTT ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durabilité) Frigate HTTP API
│
rclone → Google Drive

Structure Google Drive (par défaut)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Prérequis

  • Docker + Docker Compose
  • Un broker MQTT (ex: Mosquitto dans Home Assistant)
  • Frigate NVR avec MQTT activé
  • rclone.conf configuré avec un remote Google Drive

Installation

# 1. Cloner la branche principale
git clone https://github.com/ton-user/ton-repo.git
cd ton-repo
# 2. Initialiser la configuration
make init
# → crée config/config.yaml depuis config/config.example.yaml# 3. Copier le rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Éditer config/config.yaml
nano config/config.yaml
# 5. Builder et lancer
make build
make run
# 6. Suivre les logs
make logs

Configuration

Voir config/config.example.yaml pour la documentation complète de chaque option.

Variable d'environnementÉquivalent YAMLDescription
FRIGATE_HOSTfrigate.hostIP/hostname de Frigate
MQTT_HOSTmqtt.hostIP/hostname du broker MQTT
MQTT_USERNAMEmqtt.usernameIdentifiant MQTT
MQTT_PASSWORDmqtt.passwordMot de passe MQTT
RCLONE_REMOTErclone.remoteRemote rclone (ex: gdrive:Frigate)
SYNC_WORKERSsync.workersNombre de workers parallèles
SYNC_DRY_RUNsync.dry_runMode simulation (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Template d'arborescence

La structure des dossiers sur Google Drive est entièrement personnalisable :

sync:
path_template: "{date}/{camera}"# défaut → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Variables disponibles : {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Rétention

sync:
retention_days: 7# supprime les fichiers > 7 jours (0 = désactivé)

Le nettoyage s'effectue au démarrage puis toutes les 24h.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Dev local (Mac)

make init # crée aussi docker-compose.override.yml# éditer les host_fallback dans config/config.yaml
make build
make dev # logs en temps réel

Commandes utiles

make build # construire l'image
make run # démarrer en arrière-plan
make dev # démarrer avec logs en direct
make stop # arrêter
make logs # suivre les logs
make shell # ouvrir un shell dans le container

English

Overview

frigate-gdrive-sync is a Docker service that listens to detection events from Frigate NVR via MQTT and automatically backs up video clips, snapshots, and metadata to Google Drive using rclone.

Designed to run alongside Frigate in a Proxmox LXC container, but works from any machine on the network (Mac, other server).

Features

  • MQTT listener with automatic reconnection
  • Downloads clips (.mp4), snapshots (.jpg) and metadata (.json) from the Frigate HTTP API
  • Uploads via rclone to Google Drive (or any rclone remote)
  • Parallel workers — N cameras processed simultaneously (configurable)
  • SQLite persistent queue — no events lost after a restart
  • Retry with exponential backoff — handles clips not yet encoded by Frigate
  • Automatic retention — deletes files older than N days from Google Drive
  • Customizable folder structure via path template ({date}/{camera}, {camera}/{label}, etc.)
  • Host fallback — auto-detects whether Frigate is local or remote (useful for dev)
  • HTTP health check on /health (port 8080)
  • Dry-run mode — simulates uploads without writing to Drive
  • Structured JSON logs (or colored text for dev)

Architecture

MQTT Broker ──► MQTTListener ──► asyncio.Queue ──► Worker Pool (N workers)
│ │
SQLite (durability) Frigate HTTP API
│
rclone → Google Drive

Google Drive structure (default)

Frigate/
2026-03-15/
annke_02/
2026-03-15_14-32-07_person_abc123.mp4
2026-03-15_14-32-07_person_abc123.jpg
2026-03-15_14-32-07_person_abc123.json
foscam/
...

Requirements

  • Docker + Docker Compose
  • A MQTT broker (e.g. Mosquitto in Home Assistant)
  • Frigate NVR with MQTT enabled
  • rclone.conf configured with a Google Drive remote

Installation

# 1. Clone the main branch
git clone https://github.com/your-user/your-repo.git
cd your-repo
# 2. Initialize configuration
make init
# → creates config/config.yaml from config/config.example.yaml# 3. Copy your rclone.conf
cp ~/.config/rclone/rclone.conf config/rclone.conf
# 4. Edit config/config.yaml
nano config/config.yaml
# 5. Build and start
make build
make run
# 6. Follow logs
make logs

Configuration

See config/config.example.yaml for full documentation of each option.

Environment variableYAML equivalentDescription
FRIGATE_HOSTfrigate.hostFrigate IP/hostname
MQTT_HOSTmqtt.hostMQTT broker IP/hostname
MQTT_USERNAMEmqtt.usernameMQTT username
MQTT_PASSWORDmqtt.passwordMQTT password
RCLONE_REMOTErclone.remoterclone remote (e.g. gdrive:Frigate)
SYNC_WORKERSsync.workersNumber of parallel workers
SYNC_DRY_RUNsync.dry_runSimulation mode (true/false)
LOG_LEVELlogging.levelDEBUG / INFO / WARNING / ERROR

Path template

The Google Drive folder structure is fully customizable:

sync:
path_template: "{date}/{camera}"# default → 2026-03-15/annke_02/# path_template: "{camera}/{date}" # → annke_02/2026-03-15/# path_template: "{date}/{camera}/{label}" # → 2026-03-15/annke_02/person/

Available variables: {date}, {year}, {month}, {hour}, {camera}, {label}, {id}, {stem}

Retention

sync:
retention_days: 7# delete files older than 7 days (0 = disabled)

Cleanup runs at startup then every 24 hours.

Health check

curl http://localhost:8080/health
# {"status": "ok", "mqtt_connected": true, "pending": 0, "done": 142, "failed": 0}

Local dev (Mac)

make init # also creates docker-compose.override.yml# edit host_fallback values in config/config.yaml
make build
make dev # live logs

Useful commands

make build # build the image
make run # start in background
make dev # start with live logs
make stop # stop
make logs # follow logs
make shell # open a shell in the container

Project structure

.
├── config/
│ └── config.example.yaml # annotated configuration template
├── scripts/
│ └── test.sh # integration test suite
├── src/
│ ├── main.py # entry point, task orchestration
│ ├── config.py # Pydantic config (YAML + env vars)
│ ├── models.py # FrigateEvent dataclass
│ ├── mqtt_listener.py # MQTT subscriber with auto-reconnect
│ ├── event_queue.py # asyncio.Queue + SQLite persistence
│ ├── worker.py # download + upload worker
│ ├── frigate_client.py # Frigate HTTP API client
│ ├── rclone_uploader.py # async rclone subprocess wrapper
│ ├── retention.py # periodic GDrive cleanup
│ └── health.py # HTTP health check server
├── Dockerfile
├── docker-compose.yml
└── Makefile

Releases

Packages

Contributors

Languages