Systèmes de vidéosurveillance - présentation de Frigate
[
Présentation |
Installation de
frigate | premier lancement
| configuration | configuration avancée ( régler la détection d'objet
, activer la
détection des visages , mettre
en place une classification d'objet , mettre en place une classification
d'état , connecter
une caméra orientable PTZ compatible ONVIF , Rajouter un
certificat Let's Encrypt ( en utilisant Apache ,
en utilisant traefik ) , Faire une mise à jour
| Utilisation ( utilisation classique
, visualiser
Frigate d'un mobile ) |
Notification sur Signal via MQTT
(
Présentation ,
installation de Mosquitto
,
configuration de
Frigate et scripts de gestion des alarmes ,
envoi des alarmes avec
Signal ) |
Présentation de
Frigate+ ]
Systèmes de vidéosurveillance
Présentation de Frigate et Frigate+
14 avril 2026
Présentation
Cette section a pour objectif de
vous présenter différents outils pour monter un système de
vidéosurveillance basé sur Linux avec l'utilisation de caméras de
surveillance indépendantes (IP ou Wifi), analogique, numérique ou
de simples webcams, autrement appelé
CCTV. Sont
présentés dans cette section
Zoneminder,
Frigate
et
motionplus, ils permettent tous d'intégrer un large
panel de caméras, de faire de la détection automatique de
mouvement et de créer des événements, ils sont basés également sur
un serveur web, permettant via un navigateur de les configurer, de
visualiser en temps réel les caméras et de gérer les événements,
que ce soit sur un poste fixe ou sur un mobile.
Zoneminder
et
Frigate sont bien plus évolués et dispose de fonction
d'apprentissage automatique et de reconnaissance d'objet basé sur
l'intelligence artificielle, contrairement à
motionplus
qui est un outil bien plus simple et moins lourd à mettre en œuvre
et qui pourra être utilisé pour débuter. On pourra considérer
également que
ZoneMinder est bien plus usine à gaz que
Frigate
qui s’intègre dans
home
assistant.
Cette section est décomposée en plusieurs pages:
Pour ma part j'utilise Frigate avec l'option Frigate+
avec une architecture du système qui ressemble au schéma
ci-dessous. Frigate tourne sur un
mini PC dédié accessible d'internet avec connexion
chiffrée via un certificat Let's Encrypt le tout
géré par traefik qui gère
également l'authentification, les deux tournent sous l'outil de
conteneurisation
docker. Localement ce mini
PC se nomme Cerbere, il est assisté d'un poste
secondaire nommé Ultra qui sert à gérer une caméra bas
coût dont l'adresse
RTSP fluctue régulièrement et sur lequel tourne également
un serveur apache httpd. Cerbere
utilise une clé
Google Coral TPU pour accélérer l'exploitation des modèles
d'apprentissage. Six caméras IP sont connectées au total
réparties en extérieur, 4 sont en connexion ethernet POE
(alimentation par le câble ethernet), 3 utilisent les fonctions
PTZ
et sont mobiles. Dans les caméras on trouve un visiophone qui
est piloté d'un écran lui même connecté en intérieur en
ethernet POE, on trouve également une caméra bas coût
connecté via un répéteur WIFI qui se trouve dans un local
extérieur électrifié.
Physiquement mon système est réparti sur plusieurs zones :
- extérieur : localisation des caméras, qui toutes supportent
très bien les intempéries et le cagnard du sud.
- garage : localisation de mon serveur Cerbere et de
toutes les arrivées réseau de la maison avec un switch
classique sur lequel sont brassés les câbles RJ45 qui
desservent les différentes pièces de la maison (et qui ont
remplacé les câbles téléphoniques) et un switch POE pour les
caméras.
- mezzanine : localisation de ma box, de mon routeur et de mon
autre serveur Ultra.
- local extérieur : localisation d'un répéteur WIFI pour
étendre la portée d'une caméra fixé à l'extérieur de ce local.
- cuisine : localisation de l'écran de pilotage du visiophone
dont la caméra est intégrée au système.
Il y a pléthore de caméras IP sur le marché, les moins chères
sont souvent des modèles chinois liées à une application qui
fonctionne sous Android et à la sécurité plus que douteuse. Les
critères de choix sont :
- caméras qui génèrent un flux vidéo RTSP
avec une adresse fixe et qui vont s'intégrer très facilement à
ZoneMinder ou Frigate. Des sites comme ipcamlive
ou ispyconnect
recensent les caméras par marque ayant une adresse RTSP
fixe. Malgré cela, comme je n'avais pas intégré ce critère
initialement, j'ai une caméra dont l'adresse RSTP
change régulièrement, ce n'est pas insurmontable mais ça
complexifie l'installation car il faudra mettre en place des
scripts qui vont rendre l'adresse fixe pour ZoneMinder
ou Frigate.
- caméras configurables en se connectant en indiquant leur
adresse IP dans un navigateur sans avoir à passer par une
application. Pour les caméras bas coût, j'ai dû néanmoins
passer par l'application Android pour pouvoir les paramétrer
initialement, j'ai supprimé l'application ensuite.
- paramètres d'administration qui permettent de changer les
paramètres réseau pour les connecter à un réseau local, les
caméras ne doivent pas être directement accessibles sur
internet mais uniquement via Frigate ou ZoneMinder
- ce n'est pas strictement obligatoire, mais c'est mieux que
la caméra puisse se connecter en ethernet POE ça permet
d'avoir un seul fil (pas de câble d'alimentation, tout passe
par le câble ethernet), sur de longues distances, (mon câble
le plus long fait 30m) avec une connexion fiable et de
bonne qualité. J'ai néanmoins deux caméras bas coût
qui ne sont pas POE et qui sont alimentées avec un câble
d’alimentation en plus d'être connectées par ethernet de
manière classique, l'une d'entre elle est à plus d'une
cinquantaine de mètre, elle est connectée à un répéteur WIFI
dont le choix a été délicat car il me fallait un modèle
totalement paramétrable pour les paramètres réseau.
Il existe également un autre acteur qui m'a
donné beaucoup de fil à retordre, il s'agit du firewall
shorewall.
Il faut qu'il soit à la fois très restrictif pour interdire
tout accès aux caméras directement via internet mais également
qu'il puisse ouvrir les routes au juste besoin pour que
Frigate
soit accessible en sécurité d'un mobile sur internet via
traefik,
qui assure la connexion chiffrée avec un certificat validé par
let's encrypt et puisse communiquer avec les bases de
données
Frigate+. Et je dois avouer que je n'y serais
pas arrivé sans l'aide de
gemini enfin du
moins pas aussi rapidement.
Installation de Frigate
Frigate repose sur docker
qui a été préalablement installé.
On créera le répertoire
/etc/frigate et
/etc/frigate/config,
les enregistrements se feront dans le répertoire
/media/frigate.
On revient sous
/etc/frigate/config dans lequel j'ai créé
le fichier
docker-compose.yml qui contiendra
services:
frigate:
container_name: frigate
privileged: true # this may not be
necessary for all setups
network_mode: host # j'ai dû rajouter cette
ligne pour accéder à ma caméra restreamée avec mediamtx
restart: unless-stopped
stop_grace_period: 30s # allow enough
time to shut down the various services
image:
ghcr.io/blakeblackshear/frigate:stable
shm_size: "512mb" # update for your
cameras based on calculation above
devices:
- /dev/bus/usb:/dev/bus/usb # ligne
pour l'accélérateur USB Google Coral, à commenter sinon
-
/dev/dri/renderD128:/dev/dri/renderD128 # For intel hwaccel,
needs to be updated for your hardware
volumes:
-
/etc/localtime:/etc/localtime:ro
-
/etc/frigate/config:/config
-
/media/frigate:/media/frigate
- type: tmpfs # Optional:
1GB of memory, reduces SSD/SD Card wear
target:
/tmp/cache
tmpfs:
size: 1000000000
ports: #section inutile avec le
mode réseau host
- "8971:8971" # port
de l'interface navigateur
#- "8554:8554" # RTSP feeds,
j'ai mis en commentaire car conflit avec mediamtx, utile pour
renvoyer le flux vidéo vers homeassistant
- "8555:8555/tcp" # WebRTC
over tcp
- "8555:8555/udp" # WebRTC
over udp
[retour haut de la page]
et config.yaml dans lequel on définira les caméras et
les objets à détecter (liste par ici https://docs.frigate.video/configuration/objects)
mqtt:
enabled: false
cameras:
Camera-sud:
ffmpeg:
inputs:
- path:
rtsp://frigate:passwd@192.168.2.110
roles:
- detect
- record
hwaccel_args: preset-vaapi
objects:
track:
- person
- dog
- cat
- bird
- bicycle
- car
- motorcycle
detect:
width: 1280
height: 720
record:
enabled: true
retain:
days: 7
mode: all
Camera-entree:
ffmpeg:
inputs:
- path:
rtsp://frigate:passwd@192.168.2.112
roles:
- detect
- record
hwaccel_args: preset-vaapi
objects:
track:
- person
- dog
- cat
- bird
- bicycle
- car
- motorcycle
detect:
width: 1280
height: 720
record:
enabled: true
retain:
days: 7
mode: all
Camera-piscine:
ffmpeg:
inputs:
- path:
rtsp://frigate:passwd@192.168.2.200:554/ch0_1.264
roles:
- detect
- record
objects:
track:
- person
- dog
- cat
- bird
detect:
width: 800
height: 448
record:
enabled: true
retain:
days: 7
mode: all
Camera-ouest:
ffmpeg:
inputs:
- path:
rtsp://ultra.kervao.fr:8554/cam1
roles:
- detect
- record
objects:
track:
- person
- dog
- cat
- bird
detect:
width: 640
height: 360
record:
enabled: true
retain:
days: 7
mode: all
detectors:
cpu1:
type: cpu
num_threads: 3
detect:
enabled: true
version: 0.16-0
si vous avez un accélérateur USB Google Coral, on mettra
à la place au niveau de detectors
coral:
type: edgetpu
device: usb
à noter également si vous disposez d'un CPU ou GPU Intel pour
l'argument hwaccel_args vous avez le choix entre
- preset-vaapi
- preset-intel-qsv-h264 pour les flux H264
- preset-intel-qsv-h265 pour les flux H265
les deux derniers preset marchent sur les processeurs les plus
récents, on peut donc penser qu'ils sont plus efficaces
on tape ensuite dans ce même répertoire
docker compose -f docker-compose.yml up -d
voilà le résultat
9.6s
+] Running 10/10
✔ frigate 9 layers
[⣿⣿⣿⣿⣿⣿⣿⣿⣿]
0B/0B
Pulled
79.5s
✔ b1badc6e5066 Pull
complete
1.2s
✔ 4f4fb700ef54 Pull
complete
0.3s
✔ 14d4601b76c8 Pull
complete
14.6s
✔ cab46c26a5aa Pull
complete
1.1s
✔ 6891a7512d41 Pull
complete
14.3s
✔ b44b002328e4 Pull
complete
8.3s
✔ 8074b201d282 Pull
complete
8.6s
✔ d823104cefbd Pull
complete
9.0s
✔ f86078113133 Pull
complete
9.6s
[+] Running 2/2
✔ Network config_default
Created
0.1s
✔ Container
frigate Started
quelques commandes utiles, relancer
frigate
Premier lancement
C'est bon Frigate est installé, lancé et accessible du
navigateur localement en tapant
https://ultra.kervao.fr:8971/
pour connaitre le mot de passe il faudra taper
docker logs frigate
et on y voit
2025-09-26 17:46:21.528704726 [2025-09-26 17:46:21]
frigate.app
INFO :
********************************************************
2025-09-26 17:46:21.529867665 [2025-09-26 17:46:21]
frigate.app
INFO :
********************************************************
2025-09-26 17:46:21.530590965 [2025-09-26 17:46:21]
frigate.app
INFO : *** Auth is enabled,
but no users
exist. ***
2025-09-26 17:46:21.531237207 [2025-09-26 17:46:21]
frigate.app
INFO : *** Created a default
user:
***
2025-09-26 17:46:21.542212889 [2025-09-26 17:46:21]
frigate.app
INFO : *** User:
admin
***
2025-09-26 17:46:21.566794613 [2025-09-26 17:46:21]
frigate.app
INFO : *** Password:
2bf8aeb98g16b66f54e70a8e8f121076 ***
2025-09-26 17:46:21.577589942 [2025-09-26 17:46:21]
frigate.app
INFO :
********************************************************
2025-09-26 17:46:21.598394530 [2025-09-26 17:46:21]
frigate.app
INFO :
********************************************************
avec un TPU on devrait avoir un message qui ressemble à ça
2025-10-30 07:55:40.442764361 [2025-10-30 07:55:40]
frigate.detectors.plugins.edgetpu_tfl INFO :
TPU found
2025-10-30 07:55:40.443899970 INFO: Created
TensorFlow Lite XNNPACK delegate for CPU.
cela permet de pouvoir se connecter et voilà l'interface générale
avec les derniers évènements en haut et les vues en direct
juste en dessous
Avec seulement le TPU, autant dire que c'est inutilisable au
quotidien, le programme prend quasiment 100% des ressources
constamment.
et avec un TPU, c'est le jour et la nuit
!! D'autant qu'il n'est pas tout seul il est aidé par le GPU comme
on peut le voir.
[retour haut de la page]
Configuration
Avant d'aller plus loin il est important de connaitre quelques
notions à la base du fonctionnement de Frigate, on parle
d'alertes et de détections, les alertes sont à la base des
détections mais considérées comme des évènements prioritaires à
signaler alors que les détections sont des évènements peu
significatifs, qui ne méritent pas de notification mais qui sont
tout de même enregistrées et visibles dans la revue des évènements
(voir la documentation en anglais ici https://docs.frigate.video/configuration/review/).
Passons à la configuration accessible via la roue crantée en bas
à gauche de l'écran principal. On obtient cette interface
Dans le premier onglet Interface Utilisateur, il y a des
paramètres généraux que je n'ai pas modifiés.
On accède ensuite aux paramétrages des caméras via Paramètres
Des Caméras, le menu Gestion permet d'activer ou
désactiver les caméras, c'est utile quand une caméra pose problème
et pour éviter les messages d'erreurs.
Avant d'aller à Activités on commencera par définir les
masques et les zones de détection par via Masques/Zones,
pour chaque caméra sélectionnable à partir du bouton bleu en haut
à droite on déclare des zones de détection, les autres zones de
l'image seront ignorées pour la détection
A noter qu'on peut sélectionner le type d'objet
qui peut être détecté et estimer la vitesse du mouvement.
En revanche si on souhaite que seules les
personnes et les voitures soient considérées comme des alertes,
il faudra modifier le fichier de configuration pour la caméra en
question au niveau de la section review en rajoutant une
sous section labels comme ceci
review:
alerts:
labels:
-
person
-
car
required_zones: Zone-det-camera-sud
detections:
required_zones: Zone-det-camera-sud
On peut également déclarer des masques de mouvement pour
empêcher la détection à des endroits où on risque d'avoir des
mouvements indésirables (végétation), ça peut perturber le suivi
des objets.
pour que votre voiture garée habituellement à sa
place n'apparaisse pas comme un faux positif, il faudra créer un
masque d'objet particulier comme ceci
Au niveau de Réglage De La Détection de Mouvement, pour
chaque caméra on pourra jouer sur certains paramètres pour affiner
la détectionon, j'ai laissé les valeurs par défaut.
On revient maintenant au menu Activités, dans la
configuration ci-dessous, seulement les objets Personne et
Voiture seront affichées sous forme d'alertes dans la zone
prédéfinie et les autres objets détectés seront classés détections
dans la même zone.
et ainsi de suite pour toutes les caméras. A noter qu'il faudra
relancer Frigate pour que ça soit pris en compte, c'est
possible à partir du menu des Paramètres.
Dans le menu Enrichissements, on peut activer (ils sont
désactivés par défaut)
- la recherche sémantique qui permet de retrouver les objets
suivis dans votre revue d'évènements en utilisant soit l'image
elle-même, soit une description textuelle définie par
l'utilisateur, soit une description générée automatiquement.
- la reconnaissance faciale
- la reconnaissance des plaques d'immatriculation
- l'identification des oiseaux
Le menu
Utilisateurs comme son nom l'indique permet de gérer
les utilisateurs, deux types d'utilisateurs sont possibles les
administrateurs accèdent à l'ensemble des fonctionnalités de
l'interface, les observateurs sont limités à la consultation des
caméras, de la revue d'événements et à l'historique des
enregistrements dans l'interface utilisateur. L'onglet
Notifications
permet d'envoyer des mails pour les alertes.
Pour ce qui concerne les enregistrements, par défaut on a
record:
enabled: true
retain:
days: 7
mode: all
c'est à dire qu'alerte comme détection sont enregistrées et
conservées 7 jours. Pour une gestion plus fine des
enregistrements, voir cette page https://docs.frigate.video/configuration/record/
[retour haut de la page]
Régler la détection
d'objet
D'après la page
https://docs.frigate.video/frigate/camera_setup/#choosing-a-detect-resolution
la résolution idéale d'un objet à détecter doit tenir dans un cadre
de 320x320 pixels qui correspond au modèle utilisé par
Frigate.
Si la zone du mouvement est supérieur à 320x320, il va la recadrer
et la redimensionner s'il le faut avec éventuellement la perte de
détails supplémentaires au passage. Donc des résolutions plus
élevées n'améliorent pas significativement la précision de la
détection, en revanche elles améliorent les performances si les
objets sont très petits dans l'image.
Tout cela est assez contre intuitif car quand je dispose un cadre de
320x320 sur l'image de la caméra qui a une résolution de 1280x720,
je me dis que je suis pas prêt de détecter des personnes à cette
échelle sur cette caméra, alors qu'une résolution plus grande
pourrait permettre la détection d'objets plus petits.
En mettant la résolution maximum de ma caméra à
3072x1728, voilà à quoi correspond une boîte de 320x320 pixels,
ce n'est pas la panacée pour la détection mais c'est déjà mieux.
On peut en tirer la règle suivante : caméra avec champ de vision
proche (caméra intérieur par exemple) on la réglera avec une faible
résolution qui sera suffisante et a contrario pour une caméra avec
champ de vision éloigné (caméra extérieure essentiellement) on
choisira plutôt une grande résolution pour une meilleure détection
des objets.
Je vous enjoins à coller un cadre de 320x320 pixels sur chacune de
vos vues à l'échelle pour voir s'il est utile d'augmenter la
résolution de la caméra correspondante au regard des objets que vous
souhaitez détecter.
Maintenant en cas de faux positif, il est sans doute nécessaire
d'ajuster quelques réglages, pour les détails il faudra consulter
cette page
https://docs.frigate.video/configuration/object_filters.
En fait pour chaque objet il faut retenir plusieurs paramètres :
- score : c'est un paramètre non modifiable calculé à
chaque image pour chaque objet détecté
- min_score : tous les objets détectés dont le score est
inférieur à ce paramètre seront ignorées
- threshold : c'est la moyenne des scores pour un objet
détecté sur plusieurs images consécutives
Frigate calcule un score pour chaque objet
détecté à chaque image et l'objet est considéré comme positif
quand à la fois le score dépasse le min_score et le threshold,
c'est à dire la moyenne des scores sur plusieurs images
consécutives, ce dernier paramètre permet de confirmer la
détection.
Voilà ce qu'on pourra rajouter au fichier config.yaml
comme section commune pour l'ensemble des caméras, ce sont des
valeurs communément partagées par la communauté des utilisateurs
de Frigate.
objects:
filters:
dog:
min_score: .7
threshold: .9
cat:
min_score: .65
threshold: .8
person:
min_score: .7
threshold: .9
car:
min_score: .65
threshold: .85
Il ne faut pas considérer ces valeurs comme des
valeurs idéales, pour ma part avec des caméras extérieures qui ont
plutôt tendance à avoir un champ de vision plus lointain, j'ai
préféré rajouter une sous section filters à chaque section
objects de chacune de mes caméras pour pouvoir ajuster ces
valeurs en fonction des caméras, comme ceci
objects:
track:
- person
- dog
- cat
- face
filters:
person:
min_score: .7
threshold: .8
Pour réduire encore la détection de faux positifs
on peut définir une zone minimale et une zone maximale de
détection, c'est à dire que si l'objet est trop gros ou trop
petit, il sera automatiquement rejeté. Pour un flux avec une
résolution de 3072x1728, on peut en extraire une image à la taille
et l'ouvrir sous Gimp
Avec l'outil de sélection on trace les boîtes min et
max pour détecter une voiture (par exemple), la largeur et la
hauteur apparait en bas au milieu Rectangle: 245x252
Le paramètre de boîte de détection minimale est min_area
et a pour valeur largeur*hauteur, donc pour l'exemple ci-dessus min_area=245x252=61470,
c'est similaire pour le paramètre max_area. Dans la
pratique, j'ai mis
pour une voiture
min_area 22000
max_area 230000
pour une personne
min_area 6000
max_area 30000
ce qui donne dans config.yaml
filters:
car:
min_score: .7
threshold: .9
min_area: 22000
max_area: 230000
person:
min_score: .7
threshold: .8
min_area: 6000
max_area: 3000
Activer la
détection des visages
Pour activer la détection des visages, on commencera
par rajouter la section correspondante dans le fichier config.yaml
face_recognition:
enabled: true
et pour les caméras concernées on rajoutera dans la
sous section track la mention face
objects:
track:
- person
- dog
- cat
- bicycle
- car
- motorcycle
- face
On relance Frigate et les logs renvoient les
messages suivantes
2025-11-02 11:20:57.493001613 [2025-11-02
11:20:57]
frigate.config.config
WARNING : Camera-entree is configured to track ['face'] objects,
which are not supported by the current model.
2025-11-02 11:20:57.495025758 [2025-11-02 11:20:57]
frigate.config.config
WARNING : Camera-piscine is configured to track ['face']
objects, which are not supported by the current model.
2025-11-02 11:20:57.519957917 [2025-11-02 11:20:57]
frigate.app
INFO : Starting Frigate (0.16.1-e664cb2)
2025-11-02 11:20:57.520656637 [2025-11-02 11:20:57]
frigate.app
INFO : Creating directory:
/media/frigate/clips/faces
(...)
2025-11-02 11:20:58.822822712 [2025-11-02
11:20:58]
frigate.api.fastapi_app
INFO : FastAPI started
2025-11-02 11:21:00.117012864 [2025-11-02 11:21:00]
frigate.util.downloader
INFO : Downloading complete:
https://github.com/NickM-27/facenet-onnx/releases/download/v1.0/facenet.tflite
2025-11-02 11:21:00.269584095 [2025-11-02 11:21:00]
frigate.detectors.plugins.edgetpu_tfl INFO :
TPU found
2025-11-02 11:21:00.270930420 INFO: Created
TensorFlow Lite XNNPACK delegate for CPU.
2025-11-02 11:21:03.456767865 [2025-11-02 11:21:03]
frigate.util.downloader
INFO : Downloading complete:
https://github.com/NickM-27/facenet-onnx/releases/download/v1.0/landmarkdet.yaml
Une icône Bibliothèque de visages fait son
apparition
On rajoute des visages connus en cliquant sur Ajouter
un visage, j'ai sélectionné pour commencer deux images de
face bien identifiables, une à une
Ensuite on clique sur le bouton Entraîner
en haut à gauche et on télécharge des images avec la personne
dans différentes situations
il rajoute la photo en zoomant sur le visage
s'il a été clairement identifié, il est recommandé de rajouter
au total de 20 à 30 images pour que ça soit le plus robuste,
c'est un peu laborieux à faire car il faut y aller image par
image. Sur ma configuration les images seront placées sous
/media/frigate/clips/faces
Et voilà ce que ça va donner quand il identifie les
personnes
Maintenant vous pouvez entraîner les modèles en cliquant sur
l’icône

, on peut confirmer la détection
en cliquant sur les personnes qui ont été créées précédemment.
En revanche si
Frigate se trompe en
affichant un faux positif, on peut les supprimer en les
sélectionnant à l'aide la commande CTRL. Puis le bouton en
haut à droite
Supprimer les visages
Plus d'information par ici
https://docs.frigate.video/configuration/face_recognition.
Mettre en place une
classification d'objet
Cette fonctionnalité est apparue dans la version 0.17.0,
elle permet de créer des sous catégories d'objet, dans
l'exemple ci-dessous je vais faire un distinguo entre les
chats que mes caméras voient habituellement. Au niveau de
la fenêtre principale on cliquera sur l'icône Classification

On créera une sous catégorie d'un objet
existant, ici les chats résidents en faisant le distinguo
entre les chats

Ensuite il faudra sélectionner les images
qui correspondent au chat Plumette et idem pour l'autre
chat.
On lance ensuite l'apprentissage du
modèle
voilà ce que ce ça donne dans les
traces pour une classe voiture
2026-03-15 13:53:54.922614420 [2026-03-15
13:53:54] frigate.util.classification
INFO : Wrote
training metadata for Voitures: 32 images
2026-03-15 13:53:54.922912195
[2026-03-15 13:53:54]
frigate.util.classification INFO
: Finished training Voitures
2026-03-15 13:53:55.004893124
[2026-03-15 13:53:54]
frigate.data_processing.real_time.custom_classification
INFO : Successfully loaded updated
model for Voitures
2026-03-15 13:53:55.028924711
192.168.2.14 - - [15/Mar/2026:13:53:55 +0100]
"GET /api/classification/Voitures/dataset HTTP/1.1"
200 1399 "http://192.168.2.11:8971/classification"
"Mozilla/
5.0 (X11; Linux x86_64; rv:148.0)
Gecko/20100101 Firefox/148.0" "-"
request_time="0.004" upstream_response_time="0.003"
A partir de là les objets seront identifiés par
les sous catégories ainsi créées.
Plus d'information par ici
https://docs.frigate.video/configuration/custom_classification/object_classification
Mettre en place
une classification d'état
Cette fonctionnalité est apparue dans la version
0.17.0, elle permet de distinguer l'état d'un objet
particulier, l'ouverture d'une porte, d'un portail.
Dans l'exemple je vais considérer l'état ouvert ou
fermé du portail. Au niveau de la fenêtre principale
on choisit l'icône Classification
Dans mon exemple l'objet à considérer
est le portail et l'état ouvert ou fermé
On choisit la caméra et la zone à
surveiller pour vérifier l'état d'ouverture du portail
On clique sur Continuer, ensuite
en utilisation courante on reclique sur Classification
puis États et là on peut voir les images du
portail, on les sélectionne pour signifier l'état
Connecter
une caméra orientable PTZ compatible ONVIF
On peut également animer les
caméras
PTZ via le protocole
ONVIF, on pourra utiliser
OnvifDeviceManager présenté ici pour détecter comment
accéder aux paramètres
ONVIF de la caméra. Dans le
fichier
config.yaml au niveau la caméra concernée
on rajoutera une section
onvif après la section
ffmpeg,
comme ceci :
Camera-est:
ffmpeg:
inputs:
- path:
rtsp://user:motdepasse@192.168.2.187:554/11
roles:
- detect
- record
hwaccel_args: []
onvif:
host: 192.168.2.187
port: 8080
user: "user"
password: "motdepasse"
on relance
Frigate et les commandes font leur
apparition dans l'interface
dans les logs, à chaque commande cela
donne
2025-12-14 16:23:19.863412328
[2025-12-14 16:23:19] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.move_down for Camera-est
2025-12-14 16:23:20.014362034 [2025-12-14
16:23:20] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.stop for Camera-est
2025-12-14 16:23:24.154372463 [2025-12-14
16:23:24] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.move_left for Camera-est
2025-12-14 16:23:24.324886496 [2025-12-14
16:23:24] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.stop for Camera-est
2025-12-14 16:23:27.660911995 [2025-12-14
16:23:27] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.move_left for Camera-est
2025-12-14 16:23:27.831550797 [2025-12-14
16:23:27] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.stop for Camera-est
2025-12-14 16:23:31.340495182 [2025-12-14
16:23:31] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.move_left for Camera-est
2025-12-14 16:23:31.471007427 [2025-12-14
16:23:31] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.stop for Camera-est
2025-12-14 16:23:35.053131483 [2025-12-14
16:23:35] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.move_left for Camera-est
2025-12-14 16:23:35.203476745 [2025-12-14
16:23:35] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.stop for Camera-est
2025-12-14 16:23:38.560508556 [2025-12-14
16:23:38] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.move_left for Camera-est
2025-12-14 16:23:38.691835827 [2025-12-14
16:23:38] frigate.comms.dispatcher
INFO
: Setting ptz command to
OnvifCommandEnum.stop for Camera-est
Rajouter
un certificat Let's Encrypt
En utilisant un
serveur httpd Apache
Par défaut Frigate génère un certificat auto
signé pour utiliser le port 8971 ce qui génère un
avertissement de sécurité dans le navigateur, sous Firefox
on peut accepter le risque pour pouvoir y accéder. Mais
c'est pas génial d'autant plus si on accède à Frigate
d'internet. Dans la configuration qui est présentée ici on
utilisera apache
et non nginx comme c'est
présenté un peu partout. Pour la configuration de Let's Encrypt
avec apache on consultera cette page.
Le principe est le suivant
Internet -> HTTPS port 443 -> reverse proxy
-> HTTP interne -> Frigate port 8971
Apache fait office reverse proxy, c'est à dire
qu'il permet d’accéder à une URL interne en modifiant
automatiquement l'URL et en pointant vers le bon port. Mon
adresse accessible sur internet est
https://adresseperso.ddns.net qui pointe déjà sur
une page index.html, cette configuration permet
donc d'accéder à frigate à l'adresse https://adresseperso.ddns.net/frigate
Dans le fichier de configuration d'apache httpd.conf,
on activera les modules suivants:
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module
modules/mod_proxy_http.so
et on rajoutera l'hôte virtuel
<VirtualHost 192.168.2.13:443>
ServerName
adresseperso.ddns.net
SSLEngine on
SSLCertificateFile
/etc/letsencrypt/live/adresseperso.ddns.net/fullchain.pem
SSLCertificateKeyFile
/etc/letsencrypt/live/adresseperso.ddns.net/privkey.pem
ProxyPreserveHost
On
ProxyRequests Off
# Redirection vers Frigate sur
port 8971
ProxyPass /frigate
http://127.0.0.1:8971/frigate
ProxyPassReverse
/frigate http://127.0.0.1:8971/frigate
# Websocket support
RewriteEngine On
RewriteCond
%{HTTP:Upgrade} =websocket [NC]
RewriteRule
^/frigate/(.*) ws://127.0.0.1:8971/frigate/$1 [P,L]
</VirtualHost>
on relance apache en tapant systemctl restart
httpd
dans le fichier docker-compose.yml on
modifiera dans la section environnement le chemin par
défaut en rajoutant
environment:
FRIGATE_BASE_PATH: "/frigate"
Pour prendre en compte les modifications on stoppera
Frigate
en tapant
docker stop frigate puis
docker compose -f docker-compose.yml up -d
et on relance
Frigate en tapant
docker start frigate
En utilisant traefik
On va utiliser traefik en tant
que Reverse
Proxy, ce dernier va gèrer le certificat Let's Encrypt et
rediriger le trafic sécurisé vers Frigate. Autre
subtilité de configuration, dans ma configuration j'ai 2
serveurs :
- serveur Apache
adresse locale 192.168.2.13 accessible via monserveurapache.ddns.net
- serveur frigate adresse locale 192.168.2.11
accessible via monserveurfrigate.ddns.net
traefik va se retrouver sur le serveur frigate
et gérera aussi le certificat Let's encrypt et la
redirection du trafic sécurisé vers le serveur Apache.
Sur le box et/ou le routeur, il faut ouvrir une route vers le
serveur traefik avec l'adresse locale 192.168.2.11
vers les ports 80 (pour le renouvellement automatique du
certificat) et 443, il faudra également ouvrir les mêmes ports
avec
shorewall sur le poste traefik.
Il n'est pas nécessaire sur le router d'ouvrir la route vers
le port 8971 (connexion avec login/password sur frigate) ou
sur le port 5000 (connexion sans login/password avec frigate)
Centralisation
: traefik devient le seul point d'entrée. On
ouvre les ports 80/443 que sur le PC qui fait tourner
docker/traefik.
SSL pour tous : Le serveur httpd Apache bénéficiera
lui aussi de la connexion sécurisée HTTPS (SSL)
automatiquement, même s'il ne la gére pas lui-même. Traefik
s'occupe de déchiffrer et redirige vers la connexion non
sécurisée HTTP au serveur Apache sur le réseau local.
Renouvellement automatique : Puisque le port 80 pointe
vers traefik, Let's Encrypt pourra renouveler
les certificats de Frigate et
d'Apache sans avoir rien à faire.
En résumé le principe est le suivant pour le relais vers Apache
Internet -> HTTPS port 443 -> reverse proxy ->
HTTP interne -> Apache port 80
Pour frigate c'est un peu différent car comme on se
connecte sur son port 8971 avec une connexion chiffrée, il
faudra que traefik accepte le certificat auto signé de
Frigate, cela implique un peu de configuration
supplémentaire notamment au niveau du firewall shorewall.
Le principe de connexion est le suivant :
Internet -> HTTPS port 443 -> reverse proxy ->
HTTPS interne -> Frigate port 8971
En ce qui concerne l'authentication, traefik va gérer
le login/password et les transmettra à frigate sans
qu'il soit nécessaire à nouveau de les ressaisir via la mire
de connexion frigate.
Commençons donc par créer un répertoire /etc/traefik
dans lequel on se place et on crée un fichier vide acme.json
avec les droits 600, il contiendra les certificats.
touch acme.json
chmod 600 acme.json
ensuite on créera un fichier
traefik.yml qui contiendra
api:
dashboard: true # Active l'interface de contrôle
sur le port 8080
insecure: true # Permet l'accès direct via
le port 8080 sans SSL
# cela permet d'accepter le certicat autosigné de Frigate
serversTransport:
insecureSkipVerify: true
entryPoints:
web:
address: ":80"
http:
redirections:
entryPoint:
to:
websecure
scheme:
https
websecure:
address: ":443"
certificatesResolvers:
myresolver:
acme:
email:
olivier.hoarau@funix.org
storage: acme.json
httpChallenge:
entryPoint:
web
providers:
docker:
exposedByDefault: false # Sécurité :
n'expose que les conteneurs avec le label 'enable=true'
file:
filename: dynamic_conf.yml # Ajoute la
prise en charge du serveur Apache
watch: true
au même endroit on crée maintenant un fichier
dynamic_conf.yml qui contiendra
http:
# 1. TRANSPORTS (Pour ignorer les erreurs de
certificat auto-signé de Frigate)
serversTransports:
ignore-ssl:
insecureSkipVerify: true
# 2. ROUTERS (Configuration pour Apache)
routers:
to-apache:
rule:
"Host(`monserveurapache.ddns.net`)"
service: apache-service
entryPoints:
- websecure
tls:
certresolver:
myresolver
# 3. SERVICES (Cibles réseau pour apache)
services:
apache-service:
loadBalancer:
servers:
-
url: "http://192.168.2.13:80"
# 4. MIDDLEWARES (Centralisation de l'auth pour
Frigate)
middlewares:
frigate-auth:
basicAuth:
# liste des
utilisateurs avec htpasswd
users:
-
"frigateadmin:password-hash"
-
"frigateuser:password-hash"
frigate-header:
headers:
customRequestHeaders:
#
Traefik v3 utilise cette syntaxe pour injecter l'utilisateur
authentifié
x-forwarded-user:
'{{ printf "{{.RemoteUser}}" }}'
x-forwarded-groups:
"admin"
On créera le mot de passe en tapant
docker run --rm httpd:alpine htpasswd -nb frigateuser
motdepasse
cela doit donner directement quelque chose comme
frigateuser:password-hash
et il suffira de faire un copier coller dans le fichier
ci-dessus. La commande ci-dessous doit donner un résultat
identique
echo $(/usr/local/apache2/bin/htpasswd -nB useradmin) | sed
-e 's/\$/\$\$/g'
On va créer maintenant
docker-compose.yml qui contiendra
services:
traefik:
image: traefik:v3.0
command:
-
"--providers.docker=true"
-
"--serversTransport.insecureSkipVerify=true"
container_name:
traefik
restart: always
ports:
- "80:80"
- "443:443"
- "8080:8080" #
Dashboard (à protéger en production)
volumes:
-
/var/run/docker.sock:/var/run/docker.sock:ro
-
./traefik.yml:/traefik.yml:ro
-
./dynamic_conf.yml:/dynamic_conf.yml:ro
- ./acme.json:/acme.json
networks:
- proxy
networks:
proxy:
external: true
On modifie maintenant le fichier
docker de configuration
de
frigate /etc/frigate/config/docker-compose.yml le
voici en entier avec les lignes mises en commentaire
services:
frigate:
container_name: frigate
privileged: true # this may not be
necessary for all setups
#network_mode: host
restart: unless-stopped
stop_grace_period: 30s # allow enough
time to shut down the various services
image:
ghcr.io/blakeblackshear/frigate:0.17.0
shm_size: "540mb" # update for your
cameras based on calculation above
devices:
-
/dev/bus/usb:/dev/bus/usb # Passes the USB Coral, needs to be
modified for other versions
-
/dev/dri/renderD128:/dev/dri/renderD128 # For intel hwaccel,
needs to be updated for your hardware
volumes:
-
/etc/localtime:/etc/localtime:ro
-
/etc/frigate/config:/config
-
/media/frigate:/media/frigate
- type: tmpfs # Optional:
1GB of memory, reduces SSD/SD Card wear
target:
/tmp/cache
tmpfs:
size:
1000000000
ports:
- "8971:8971"
#- "5000:5000" # Internal
unauthenticated access. Expose carefully.
- "8554:8554" # RTSP feeds
- "8555:8555/tcp" # WebRTC
over tcp
- "8555:8555/udp" # WebRTC
over udp
environment:
#-
FRIGATE_BASE_PATH="/frigate"
-
PLUS_API_KEY=clé-frigate-plus
-
FRIGATE_AUTH_METHOD=proxy
-
FRIGATE_PROXY_HEADER=Remote-User
-
FRIGATE_TRUSTED_PROXIES=172.18.0.0/16
networks:
- proxy # Doit être sur le
même réseau que Traefik
labels:
- "traefik.enable=true"
-
"traefik.http.routers.frigate.rule=Host(`monserveurfrigate.ddns.net`)"
-
"traefik.http.routers.frigate.entrypoints=websecure"
-
"traefik.http.routers.frigate.tls.certresolver=myresolver"
# Appelle les middlewares
définis dans le fichier (d'où le @file)
-
"traefik.http.routers.frigate.middlewares=frigate-auth@file,frigate-header@file"
# Configuration du service
vers le port 8971
-
"traefik.http.services.frigate-service.loadbalancer.server.port=8971"
-
"traefik.http.services.frigate-service.loadbalancer.server.scheme=https"
# UTILISATION DU TRANSPORT
DEFINI DANS LE FICHIER DYNAMIQUE
-
"traefik.http.services.frigate-service.loadbalancer.serverstransport=ignore-ssl@file"
networks:
proxy:
external: true
dans le fichier
/etc/frigate/config/config.yaml on aura
bien
tls:
enabled: true
auth:
enabled: true
proxy:
header_map:
user: x-forwarded-user
role: x-forwarded-groups
Avant de lancer
traefik et relancer
frigate il
faudra créer le réseau
docker avec le nom
proxy
en tapant
docker network create proxy
cela va donner le numéro d'identification du réseau
proxy
avec une longue suite de chiffres et de lettres accolés
entre eux. J'ai ensuite simplifié la configuration d'
apache
en supprimant toutes les
VirtualHost en lien avec mon
adresse
monserveurapache.ddns.net ou les redirections
automatiques du port 80 vers 443. Comme
traefik va
maintenant envoyer les requêtes à Apache en HTTP (port 80) sur
votre réseau local, je l'ai remis en écoute sur le port 80 par
défaut.
Passons maintenant à la configuration de
shorewall
sous
/etc/shorewall tout d'abord fichier
shorewall.conf, il faut veiller à avoir
DOCKER=Yes
DOCKER_BRIDGE=docker0
IP_FORWARDING=Keep
ROUTE_FILTER=No
Fichier
interfaces
#
# Shorewall -- /etc/shorewall/interfaces
#
# For information about entries in this file, type "man
shorewall-interfaces"
#
# The manpage is also online at
#
https://shorewall.org/manpages/shorewall-interfaces.html
#
?FORMAT 2
- enp1s0
proxyarp,dhcp,nosmurfs,routefilter
# On utilise 'physical' pour éviter que Shorewall ne
cherche le broadcast
dock docker0
physical=docker+,routeback=1
dock br
physical=br-+,routeback=1
fichier
zones
#
# Shorewall -- /etc/shorewall/zones
#
# For information about this file, type "man
shorewall-zones"
#
# The manpage is also online at
# https://shorewall.org/manpages/shorewall-zones.html
#
###############################################################################
#ZONE
TYPE
OPTIONS
IN_OPTIONS
OUT_OPTIONS
fw
firewall
loc ipv4
net ipv4
dock ipv4
fichier
snat
#
# Shorewall -- /etc/shorewall/snat
#
# For information about entries in this file, type "man
shorewall-snat"
#
# See https://shorewall.org/manpages/shorewall-snat.html
for more information
#
?FORMAT 2
###################################################################################################################################################
#ACTION
SOURCE
DEST
PROTO
DPORT SPORT IPSEC
MARK USER
SWITCH ORIGDEST
PROBABILITY
MASQUERADE 172.18.0.0/16
enp1s0
MASQUERADE 172.17.0.0/16
enp1s0
fichier
policy
#
# Shorewall -- /etc/shorewall/policy
#
# For information about entries in this file, type "man
shorewall-policy"
#
# The manpage is also online at
# https://shorewall.org/manpages/shorewall-policy.html
#
###############################################################################
$FW dock
ACCEPT
dock $FW
ACCEPT
dock dock
ACCEPT
dock net
ACCEPT
fw all
ACCEPT
loc all
ACCEPT
all all
REJECT
Fichier
rules
#
# Shorewall -- /etc/shorewall/rules
#
# For information on the settings in this file, type "man
shorewall-rules"
#
# The manpage is also online at
# https://shorewall.org/manpages/shorewall-rules.html
#
##############################################################################################################################################################
#ACTION
SOURCE
DEST
PROTO
DPORT SPORT ORIGDEST
RATE
USER MARK
CONNLIMIT
TIME
HEADERS SWITCH HELPER
#INCLUDE
rules.drakx
#
==============================================================================
# 1. FLUX DOCKER (FRIGATE / TRAEFIK INTERNAL)
#
==============================================================================
# Communication entre l'hôte et les conteneurs (Port Frigate+)
ACCEPT $FW
dock:172.18.0.0/16
tcp 8971
ACCEPT dock:172.18.0.0/16 $FW
tcp
8971
# Sortie DNS pour les conteneurs (indispensable pour Frigate+)
ACCEPT dock:172.18.0.0/16 net
udp
53
ACCEPT dock:172.18.0.0/16 net
tcp
53
# Sortie HTTPS pour les conteneurs (Upload photos Frigate+)
ACCEPT dock:172.18.0.0/16 net
tcp
443
#
==============================================================================
# 2. ACCÈS TRAEFIK (HTTP/HTTPS)
#
==============================================================================
# On autorise le Web depuis Internet ET depuis le réseau local
# Note : On utilise $FW car 192.168.2.11 est l'IP de cette
machine.
ACCEPT net
$FW
tcp
80,443
ACCEPT loc
$FW
tcp
80,443
# Ports spécifiques (WebRTC / Go2RTC)
ACCEPT net
$FW
tcp
8555
ACCEPT net
$FW
udp
8555
ACCEPT loc
$FW
tcp
8555
ACCEPT loc
$FW
udp
8555
# Redirection du trafic Web vers le conteneur Traefik
DNAT net dock:172.18.0.2
tcp 80,443
DNAT loc dock:172.18.0.2
tcp 80,443
#
==============================================================================
# 3. ACCÈS LOCAL & ADMINISTRATION (SSH, MQTT, FRIGATE UI)
#
==============================================================================
# Autorise ton LAN à administrer le serveur
ACCEPT loc
$FW
tcp
22,1883,5000,8080,8971,8554
ACCEPT loc
$FW
udp
554,2049,8000
ACCEPT loc
$FW
icmp
#
==============================================================================
# 4. SORTIE SERVEUR (PING & MAJ)
#
==============================================================================
ACCEPT $FW
net
icmp
ACCEPT $FW
net
tcp
80,443
ACCEPT $FW
net
udp
53
#
==============================================================================
# 5. FLUX DOCKER VERS LAN (POUR APACHE EXTERNE)
#
==============================================================================
# Autorise Traefik (zone dock) à joindre Apache (zone loc)
ACCEPT dock:172.18.0.0/16
loc:192.168.2.13 tcp
80
#
==============================================================================
# 6. FLUX FRIGATE -> CAMÉRAS (RÉSEAU LOCAL)
#
==============================================================================
# Autorise Frigate à lire les flux RTSP (vidéo) et HTTP
(commandes/snapshot)
ACCEPT dock:172.18.0.0/16
loc tcp
554,80,81,8000,8554
ACCEPT dock:172.18.0.0/16
loc udp
554,8000-8010
On relance
shorewall
Maintenant
on va lancer
traefik, sous
/etc/traefik on tapera
docker compose up -d
et on relance la configuration de
frigate en tapant
docker stop frigate
cd /etc/frigate/config
docker compose down
docker compose up -d
pour voir si ça fonctionne on pourra taper
docker
network inspect proxy voilà le résultat
[
{
"Name":
"proxy",
"Id":
"id-reseau-proxy",
"Created":
"2026-03-21T07:40:45.423464906+01:00",
"Scope":
"local",
"Driver":
"bridge",
"EnableIPv4":
true,
"EnableIPv6":
false,
"IPAM": {
"Driver":
"default",
"Options":
{},
"Config":
[
{
"Subnet":
"172.18.0.0/16",
"Gateway":
"172.18.0.1"
}
]
},
"Internal":
false,
"Attachable":
false,
"Ingress":
false,
"ConfigFrom":
{
"Network":
""
},
"ConfigOnly":
false,
"Containers":
{
"1935c6946444a4be193c3fc3cf89ad4e00d76b0dace34c032266c72a36789caf":
{
"Name":
"frigate",
"EndpointID":
"e3630a1c73245a57c88048edbb1c9e49dee86d925ff8a735c42827b1b4959823",
"MacAddress":
"06:fa:01:8a:b1:5a",
"IPv4Address":
"172.18.0.2/16",
"IPv6Address":
""
},
"564a20b201a1adf544020be253b267f5472c3cceec0cdc31f208b4f02089141e":
{
"Name":
"traefik",
"EndpointID":
"671f4968920ec3497c8bbfe8855c99e10626907159abc374bf5d0be8ea555bbd",
"MacAddress":
"46:2e:a8:5b:bc:ec",
"IPv4Address":
"172.18.0.3/16",
"IPv6Address":
""
}
},
"Options": {},
"Labels": {}
}
]
On voit bien les instances
traefik et
frigate
sont bien sur le même réseau
proxy.
On pourra aller maintenant sur http://192.168.2.11:8080 pour
voir le tableau de bord de
traefik, on pourra vérifier
si les routes sont actives et les certificats valides.
En cliquant sur
Explore au niveau de
Routers, on
peut voir à la fois
frigate et le serveur
httpd
apache avec chacun un certificat valide.
J'ai gardé le port ouvert 8080 sur le réseau local mais il est
non accessible d'internet.
Au besoin visualiser le fichier
acme.json vous devriez
retrouver vos certificats et on pourra afficher les logs de
traefik
en tapant
docker logs -f traefik
Faire une mise à jour
Pour faire une mise à
jour on commence par stopper
frigate en tapant
docker stop frigate
on édite maintenant le fichier
docker-compose.yml et au
niveau de image on indique la dernière version stable
services:
frigate:
(...)
image:
ghcr.io/blakeblackshear/frigate:0.17.0
On prend en compte la modification en tapant
docker compose up -d
voilà ce que ça donne
[+] Running 11/11
✔ frigate 10 layers [⣿⣿⣿⣿⣿⣿⣿⣿⣿⣿]
0B/0B
Pulled
160.9s
✔ 4831516dd0cb Pull complete
1.9s
✔ 4f4fb700ef54 Pull complete
1.2s
✔ cb7d423543ee Pull complete
19.8s
✔ d2f5da7ad830 Pull complete
2.6s
✔ 7e04514a5073 Pull complete
32.6s
✔ 34300798769b Pull complete
5.7s
✔ 2ad10e3dbd66 Pull complete
18.0s
✔ 848dd1cbc10e Pull complete
18.5s
✔ 8226412a03ca Pull complete
19.0s
✔ b22355f413a7 Pull complete
19.8s
[+] Running 2/2
✔ Container frigate
Started
12.1s
! frigate Published ports are discarded when using host
network mode
0.0s
et on peut voir dans les logs que c'est bien pris en compte en
tapant
docker logs frigate
on peut voir
2026-02-27 18:03:04.431938998
[2026-02-27 18:03:04] frigate.app
INFO
: Starting Frigate (0.17.0-f0d69f7)
Si vous avez l'erreur
[2026-02-27 18:03:15] frigate.api.auth
ERROR
: Error parsing jwt: bad_signature:
il faudra stopper
frigate, supprimer le fichier
/etc/frigate/config/.jwt_secret
et vider le cache du navigateur qui accède à
frigate
et on relance
frigate.
Pour l'erreur suivante
2026-02-27 18:03:15.508446035 Fatal Python error:
Illegal instruction
2026-02-27 18:03:15.508451526
2026-02-27 18:03:15.508494078 Thread
0x00007f2970ce66c0 (most recent call first):
2026-02-27 18:03:15.508587864 File
"/usr/lib/python3.11/threading.py", line 320 in wait
2026-02-27 18:03:15.508683237 File
"/usr/lib/python3.11/queue.py", line 171 in get
2026-02-27 18:03:15.508775665 File
"/usr/local/lib/python3.11/dist-packages/playhouse/sqliteq.py",
line 162 in loop
2026-02-27 18:03:15.508860665 File
"/usr/local/lib/python3.11/dist-packages/playhouse/sqliteq.py",
line 137 in run
2026-02-27 18:03:15.508965544 File
"/usr/local/lib/python3.11/dist-packages/playhouse/sqliteq.py",
line 272 in run
2026-02-27 18:03:15.509051339 File
"/usr/lib/python3.11/threading.py", line 975 in run
2026-02-27 18:03:15.509143141 File
"/usr/lib/python3.11/threading.py", line 1038 in
_bootstrap_inner
2026-02-27 18:03:15.509234196 File
"/usr/lib/python3.11/threading.py", line 995 in _bootstrap
2026-02-27 18:03:15.509249695
2026-02-27 18:03:15.509286238 Current thread
0x00007f299b08a040 (most recent call first):
2026-02-27 18:03:15.509368220 File
"<frozen importlib._bootstrap>", line 241 in
_call_with_frames_removed
2026-02-27 18:03:15.509501615 File
"<frozen importlib._bootstrap_external>", line 1233
in create_module
2026-02-27 18:03:15.509584820 File
"<frozen importlib._bootstrap>", line 573 in
module_from_spec
(...)
2026-02-27 18:03:15.514956630 File
"/usr/lib/python3.11/multiprocessing/spawn.py", line 133
in _main
2026-02-27 18:03:15.514958723 File
"/usr/lib/python3.11/multiprocessing/forkserver.py", line
313 in _serve_one
2026-02-27 18:03:15.514960962 File
"/usr/lib/python3.11/multiprocessing/forkserver.py", line
274 in main
2026-02-27 18:03:15.514962618 File
"<string>", line 1 in <module>
Dans Frigate 0.17, les nouvelles fonctionnalités d'
embeddings
(recherche sémantique, reconnaissance faciale, etc.)
utilisent des modèles IA plus complexes via
TensorFlow
et
Jina. Ces bibliothèques sont compilées pour des
processeurs modernes supportant les instructions
AVX/AVX2.
Pour savoir si votre processeur dispose de ces instructions
il faut taper
grep -o 'avx[^ ]*' /proc/cpuinfo
s'il y a rien qui sort c'est que le processeur est trop
ancien, la désactivation de la recherche sémantique suffit à
résoudre le problème dans le fichier
config.yaml.
semantic_search:
enabled: false
J'ai fait
plutôt le choix de basculer sur un mini PC avec un N150 qui
comprend les instructions
AVX. Plus d'info sur la
migration par là
https://docs.frigate.video/frigate/updating/
[retour haut de la page]
Utilisation
Utilisation classique
Revenons maintenant à l'interface principale, on a vu plus haut
que la vue principale renvoie vers les vues des caméras, elle est
accessible en cliquant sur l'icône représentant une caméra sur la
gauche.
En cliquant à gauche sur la Revue des évènements, on voit
s'afficher tous les derniers évènements (alertes, détections,
mouvement). L'objet détecté apparait en icône dans le coin en haut
à gauche de l'image, on accède au replay en cliquant sur l'image.
On acte la revue en cliquant en bas sur Marquer ces éléments
comme passés en revue
Quand on clique sur la petite icône en haut à
gauche qui symbolise l'objet détecté, on tombe sur les détails
de l'évènement, à droite on retrouve une frise temporelle avec
les derniers évènements de la journée.
on peut aller encore plus loin en cliquant sur l'image de
l'objet détecté, on tombe sur une fenêtre qui permet de
visualiser la vidéo avec des détails succincts sur la détection.
Quand on clique sur les ... à droite de l'objet
détecté on tombe sur ce menu pour aller plus loin
Pour afficher la cinématique de l'objet on
cliquera sur Afficher le parcours de l'objet dans
l'image ci-dessous la trajectoire peut paraitre bizarre car la
caméra est PTZ et s'est orientée vers l'objet pour le suivre
automatiquement
Le menu Explorer à gauche permet
d'afficher tous les objets détectés qu'on peut filtrer avec les
outils en haut à droite
Quand on clique sur une image de détection on peut
visualiser la cinématique de l'objet de manière plus détaillée
avec les paramètres de détection qui pourront servir à affiner
la configuration de frigate.
Vous pouvez les supprimer un à un à l'aide du menu contextuel,
ou par paquet avec un CTRL-A puis le bouton Supprimer en
haut à droite
On a vu plus haut qu'on
pouvait accéder à un état des ressources du système via le menu
Paramètres->Système->Métriques du système, il y a
également un onglet Stockage qui donne un état des
enregistrements
Et l'onglet Caméras qui donne un état
des ressources utilisées par chaque caméra, même si on ne voit
pas le TPU
Pour le reste, je vous renvoie à la
documentation de frigate pour l'utilisation avec
quelques URL intéressantes
https://docs.frigate.video/guides/getting_started
https://community.jeedom.com/t/tuto-integrer-frigate-et-faire-de-la-reconnaissance-video-dobjet-par-ia-en-local-dans-son-jeedom/117108
https://www.simplehomelab.com/frigate-docker-guide/
Visualiser Frigate
d'un mobile
Pour ce qui concerne la visualisation à distance sur un mobile,
il existe bien une application
Android non officielle, mais j'en vois pas trop l'intérêt
car de base en accédant directement à l'adresse (dès lors qu'on
l'a rendu accessible sur internet) à partir d'un navigateur du
mobile, c'est plutôt convivial comme on peut le voir ci-dessous

[
Retour
haut de la page]
Notifications avec
Signal via MQTT
Présentation
Frigate intègre déjà un service de notification par mail
comme évoqué plus haut qui ne marche pas chez moi, mais peu
importe ce paragraphe explique recevoir les notifications
d'alerte avec
Signal en utilisant le service
MQTT. MQTT
(Message Queuing Telemetry Transport) est un protocole de
messagerie qui fonctionne sur le principe de souscription /
publication, c'est à dire qu'un serveur (ou broker) peut publier
des notifications sur un canal et des clients peuvent soucrire
pour visualiser les notifications. Pour ce qui concerne
Frigate,
en activant
MQTT, on pourra lancer un script qui
déclenche une action à la réception d'un évènement comme une
alerte, il est possible également que le broker
MQTT
soit accessible d'internet et une application cliente
MQTT
android peut être installé pour être prévenu des alertes.
Installation de
Mosquitto
Le site officiel
https://mosquitto.org,
sur ma mageia je me suis contenté de l'installer en tapant
urpmi mosquitto
on crée un utilisateur avec son mot de passe
mosquitto_passwd -c /etc/mosquitto/passwd olivier
Password:
Reenter password:
dans le fichier
/etc/mosquitto/mosquitto.conf on
décommente et modifie les lignes suivantes
allow_anonymous false
password_file /etc/mosquitto/passwd
listener 1883 0.0.0.0
on change le propriétaire du fichier
passwd
chown mosquitto:mosquitto /etc/mosquitto/passwd
on peut lancer
mosquitto
systemctl start mosquitto
et voilà ce que donne la commande
systemctl status mosquitto
● mosquitto.service - Mosquitto MQTT Broker
Loaded: loaded
(/usr/lib/systemd/system/mosquitto.service; disabled;
preset: disabled)
Active: active (running)
since Sun 2025-12-07 09:14:56 CET; 2min 12s ago
Docs:
man:mosquitto.conf(5)
man:mosquitto(8)
Process: 1426932
ExecStartPre=/bin/mkdir -m 740 -p /var/log/mosquitto
(code=exited, status=0/SUCCESS)
Process: 1426933
ExecStartPre=/bin/chown mosquitto:mosquitto /var/log/mosquitto
(code=exited, status=0/SUCCESS)
Process: 1426934
ExecStartPre=/bin/mkdir -m 740 -p /run/mosquitto (code=exited,
status=0/SUCCESS)
Process: 1426935
ExecStartPre=/bin/chown mosquitto:mosquitto /run/mosquitto
(code=exited, status=0/SUCCESS)
Main PID: 1426936 (mosquitto)
Tasks: 1 (limit:
18901)
Memory: 1004.0K
CPU: 43ms
CGroup:
/system.slice/mosquitto.service
└─1426936
/usr/sbin/mosquitto -c /etc/mosquitto/mosquitto.conf
déc. 07 09:14:56 ultra.kervao.fr systemd[1]: Starting
mosquitto.service...
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: mosquitto version 2.0.21 starting
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: Config loaded from /etc/mosquitto/mosquitto.conf.
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: Starting in local only mode. Connections will only
be possible from clients running on this machine.
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: Create a configuration file which defines a
listener to allow remote access.
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: For more details see
https://mosquitto.org/documentation/authentication-methods/
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: Opening ipv4 listen socket on port 1883.
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: Opening ipv6 listen socket on port 1883.
déc. 07 09:14:56 ultra.kervao.fr mosquitto[1426936]:
1765095296: mosquitto version 2.0.21 running
déc. 07 09:14:56 ultra.kervao.fr systemd[1]: Started
mosquitto.service.
on n'oublie pas d'ouvrir le port TCP 1883 utilisé par
MQTT
via
shorewall
Pour voir si ça fonctionne bien on peut lancer un client qui va
attendre une notification d'un broker
mosquitto_sub -v -t 'test/topic' -u olivier -P motdepasse
Maintenant on va lancer un broker en publiant une notification
mosquitto_pub -u olivier -P motdepasse -t
'test/topic' -m 'helloWorld'
et du client on va voir s'afficher
test/topic helloWorld
A noter que le broker tourne sur le serveur où se trouve
Frigate,
l'ensemble tourne en local et je n'ai pas besoin qu'il soit
accessible d'internet.
Configuration
de Frigate et scripts de gestion des alertes
Maintenant dans le fichier de configuration de
Frigate
config.yaml, on va activer
MQTT
mqtt:
enabled: true
host: localhost
user: olivier
password: motdepasse
port: 1883
on va créer le script d'écoute
/usr/local/bin/alerte_frigate
qui va envoyer un mail dès qu'il y a une alerte, on verra
plus loin pour Signal.
#!/bin/bash
mosquitto_sub -t "frigate/events" -u olivier -P
motdepasse | while read -r payload
do
#à décommenter pour visualiser pour
des tests de fonctionnement
#echo "Rx MQTT: ${payload}"
#envoi d'un mail pour chaque nouveau
évènement
if echo "${payload}" | grep -q
'"type": "new"'; then
echo
"${payload}" | mail -s "Frigate alerte" olivier
fi
done
le mail contiendra
{"before": {"id": "1765103169.376268-4ybyyv", "camera":
"Camera-sud", "frame_time": 1765103169.376268, "snapshot":
null, "label": "car", "sub_label": null, "top_score": 0.0,
"false_positive": true, "start_time": 1765103169.376268,
"end_time": null, "score": 0.9765625, "box": [1876, 1001,
2407, 1285], "area": 150804, "ratio": 1.869718309859155,
"region": [1356, 0, 3072, 1716], "active": true, "stationary":
false, "motionless_count": 0, "position_changes": 0,
"current_zones": [], "entered_zones": [], "has_clip": false,
"has_snapshot": false, "attributes": {}, "current_attributes":
[], "pending_loitering": false, "max_severity": null,
"current_estimated_speed": 0, "average_estimated_speed": 0,
"velocity_angle": 0, "path_data": [],
"recognized_license_plate": null}, "after": {"id":
"1765103169.376268-4ybyyv", "camera": "Camera-sud",
"frame_time": 1765103169.59021, "snapshot": {"frame_time":
1765103169.376268, "box": [1876, 1001, 2407, 1285], "area":
150804, "region": [1356, 0, 3072, 1716], "score": 0.9765625,
"attributes": [], "current_estimated_speed": 0,
"velocity_angle": 0, "path_data": [],
"recognized_license_plate": null,
"recognized_license_plate_score": null}, "label": "car",
"sub_label": null, "top_score": 0.9765625, "false_positive":
false, "start_time": 1765103169.376268, "end_time": null,
"score": 0.9765625, "box": [1872, 1003, 2411, 1287], "area":
153076, "ratio": 1.897887323943662, "region": [1356, 0, 3072,
1716], "active": true, "stationary": false,
"motionless_count": 1, "position_changes": 0, "current_zones":
[], "entered_zones": [], "has_clip": false, "has_snapshot":
false, "attributes": {}, "current_attributes": [],
"pending_loitering": false, "max_severity": null,
"current_estimated_speed": 0, "average_estimated_speed": 0,
"velocity_angle": 0, "path_data": [[[0.6969, 0.7448],
1765103169.59021]], "recognized_license_plate": null}, "type":
"new"}
le
script va filtrer les nouvelles alertes uniquement, en revanche
il prendra aussi bien les alertes que les détections, il
n'existe pas de champs qui les distinguent.
Voilà un script plus évolué (merci
ChatGPT !!) qui
permettra d'envoyer un mail d'alerte uniquement pour les objets
person et
car en y joignant la photo instantanée
avec le contour autour de l'objet. Il nécessitera l'installation
du package
jq qui permettra d'extraire plus facilement
des informations utiles.
#!/bin/bash
# /usr/local/bin/alerte_frigate
# Attendre que le clip soit complètement écrit (taille
stable) avant envoi
#paramètres de connexion MQTT"
MQTT_USER="olivier"
MQTT_PASS="motdepasse"
MQTT_TOPIC="frigate/events"
#paramètre de connexion API FRIGATE
FRIGATE_USER="loginfrigate"
FRIGATE_PASS="motdepasse"
FRIGATE_API="https://192.168.2.11:8971"
COOKIE_FILE="/tmp/frigate_cookies.txt"
CLIP_DIR="/media/frigate/clips"
MAIL_FROM="webmaster@funix.org"
MAIL_TO="olivier.hoarau@funix.org"
THROTTLE_SECONDS=40
# délai minimum
entre deux alertes par caméra
THROTTLE_DIR="/var/tmp/frigate_throttle"
mkdir -p "$THROTTLE_DIR"
SIGNAL_USER="+336XXXXXXXX"
# ton numéro Signal
SIGNAL_DEST="+336YYYYYYYY"
# numéro qui reçoit les
alertes
LOGGER_TAG="alerte_frigate"
### --- LOG FUNCTION ---
log() { logger -t "$LOGGER_TAG"
"[INFO] $*"; }
log_warn(){ logger -t "$LOGGER_TAG" "[WARN] $*"; }
log_dbg() { logger -t "$LOGGER_TAG" "[DEBUG] $*"; }
log "Démarrage du service."
# Paramètres d'attente pour la stabilité du fichier
WAIT_MAX_SECS=20 #
temps max d'attente pour que le fichier soit complet
CHECK_STEP=0.5
# intervalle
entre deux vérifs de taille (sec)
STABLE_ROUNDS=2
# nombre de mesures
identiques successives pour considérer "stable"
# Fonction qui permet une alerte max par caméra toutes
les THROTTLE_SECONDS secondes
should_throttle() {
local cam="$1"
local now
now=$(date +%s)
local file="$THROTTLE_DIR/$cam.last"
# Si jamais aucun envoi encore
if [ ! -f "$file" ]; then
echo "$now"
> "$file"
return 1
# PAS de throttle
fi
local last
last=$(cat "$file")
local delta=$((now - last))
if [ "$delta" -lt "$THROTTLE_SECONDS"
]; then
# throttle
actif
return 0
fi
# assez de temps écoulé, mise à jour
echo "$now" > "$file"
return 1
}
# Premier login au lancement du script
#login_frigate
mosquitto_sub -t "$MQTT_TOPIC" -u "$MQTT_USER" -P
"$MQTT_PASS" | while read -r payload
do
# Ne traiter que les "new"
if echo "$payload" | jq -e .
>/dev/null 2>&1; then
if ! echo
"$payload" | grep -q '"type"[[:space:]]*:[[:space:]]*"new"';
then
continue
fi
else
continue
fi
# Extraire infos
camera=$(echo "$payload" | jq -r
'.after.camera // .camera // empty')
label=$(echo "$payload" | jq -r
'.after.label // "inconnu"')
id=$(echo "$payload" | jq -r
'.after.id // .id // empty')
# THROTTLE PAR CAMERA
if should_throttle "${camera}"; then
log_dbg
"Throttle actif : alerte ignorée sur ${camera} (moins de
$THROTTLE_SECONDS secondes)"
continue
fi
# Filtrer uniquement les labels car et
person
if [[ "${label}" != "car" &&
"${label}" != "person" ]]; then
log_dbg
"Événement ignoré pour label=${label}"
continue
fi
if [ -z "$id" ] || [ -z "${camera}" ];
then
log_warn
"Événement MQTT invalide, ignoré."
continue
fi
EVENT_ID="$id"
log "Détection : caméra=${camera},
label=${label}, id=${EVENT_ID}"
log_dbg "Recherche du fichier annoté…"
CLIP_FILE=""
MAX_WAIT=20 # secondes
WAIT=0
while [ $WAIT -lt $MAX_WAIT ]; do
CLIP_FILE=$(find
"$CLIP_DIR" -type f -iname "*${EVENT_ID}*.jpg" | head -n 1)
if [ -n
"$CLIP_FILE" ]; then
log_dbg
"Fichier trouvé après ${WAIT}s : $CLIP_FILE"
break
fi
sleep 1
WAIT=$((WAIT+1))
done
if [ -z "$CLIP_FILE" ]; then
log_warn
"Aucun snapshot annoté trouvé pour $EVENT_ID après
${MAX_WAIT}s."
else
log
"[INFO] Clip annoté trouvé: $CLIP_FILE"
fi
ATTACH=""
# Si clip trouvé, attendre la
stabilisation de la taille
if [[ -n "$CLIP_FILE" && -f
"$CLIP_FILE" ]]; then
log "Clip
candidate trouvé: $CLIP_FILE"
elapsed=0
stable_count=0
last_size=-1
while ((
$(echo "$elapsed < $WAIT_MAX_SECS" | bc -l) )); do
if
[[ -f "$CLIP_FILE" ]]; then
size=$(stat
-c %s "$CLIP_FILE" 2>/dev/null || echo 0)
else
size=0
fi
if
[[ "$size" -eq "$last_size" && "$size" -gt 0 ]]; then
stable_count=$((stable_count+1))
else
stable_count=0
fi
#
Si on a STABLE_ROUNDS mesures identiques => on le considère
complet
if
(( stable_count >= STABLE_ROUNDS )); then
log
"Fichier stable (taille=$size). Prêt à être envoyé."
ATTACH="$CLIP_FILE"
break
fi
last_size=$size
sleep
"$CHECK_STEP"
elapsed=$(echo
"$elapsed + $CHECK_STEP" | bc -l)
done
# si pas
stable au bout du timeout, on considère quand même (mais on
peut fallback)
if [[ -z
"$ATTACH" ]]; then
log_warn
"Fichier non stable après ${WAIT_MAX_SECS}s (taille
actuelle=${last_size}). Tentative fallback API."
fi
else
log_warn
"Aucun clip annoté trouvé localement pour ${EVENT_ID}."
fi
# Si pas d'attach encore, tenter de
récupérer la snapshot via API
if [[ -z "$ATTACH" ]]; then
TMPFILE="/tmp/frigate_snapshot_${EVENT_ID//[^a-zA-Z0-9._-]/_}.jpg"
rm -f
"$TMPFILE"
# Récupération
via API (retry court car la snapshot peut être générée juste
après l'event)
got=0
retries=10
sleep_between=0.5
#connexion sécurisée à
l'API FRIGATE en passant par la création d'un cookie
curl -k -c
${COOKIE_FILE} -X POST -d
"user=${FRIGATE_USER}&password=${FRIGATE_PASS}"
"${FRIGATE_API}/api/login"
for
((i=0;i<retries;i++)); do
curl
-k -c ${COOKIE_FILE} -s -f
"${FRIGATE_API}/api/events/${EVENT_ID}/snapshot.jpg" -o
"$TMPFILE"
if
[[ $? -eq 0 && -s "$TMPFILE" ]]; then
log
"Snapshot récupérée via API -> $TMPFILE"
ATTACH="$TMPFILE"
got=1
break
fi
sleep
"$sleep_between"
done
if [[ $got -ne
1 ]]; then
log_warn
"API snapshot échouée ou introuvable pour ${EVENT_ID}."
fi
fi
### --- MAIL HTML ---
subject="Frigate : détection de
${label} sur ${camera}"
body="Nouvelle détection
Frigate.\n\nCaméra : ${camera}\nObjet : ${label}\nID
: ${EVENT_ID}\n\nPayload brut
:\n${payload}"
if [[ -n "$ATTACH" && -f
"$ATTACH" ]]; then
echo -e "$body" |
mail -s "$subject" -r "$MAIL_FROM" -a "$ATTACH" "$MAIL_TO"
log "Mail envoyé
avec pièce jointe : $ATTACH"
# si tmp file, on
peut le supprimer
if [[ "$ATTACH" ==
/tmp/frigate_snapshot_* ]]; then
rm -f
"$ATTACH"
fi
else
echo -e "$body" |
mail -s "$subject" -r "$MAIL_FROM" "$MAIL_TO"
log "Mail envoyé
sans pièce jointe."
fi
done
on va créer un service
systemd pour que le script
soit lancé automatiquement, voilà le contenu de
/usr/lib/systemd/system/frigate_alert.service
[Unit]
Description=Frigate MQTT Alert Email Service
After=network.target
[Service]
Type=simple
ExecStart=/usr/local/bin/alerte_frigate
Restart=always
RestartSec=5
User=root
Environment=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
[Install]
WantedBy=multi-user.target
on l'active en tapant
systemctl enable frigate_alert
et on lance via la commande
systemctl
start frigate_alert
on pense à relancer
Frigate
car on a touché à sa configuration
docker stop frigate
docker start frigate
voilà ce que renvoie
journalctl
déc. 07 12:20:43 ultra.kervao.fr systemd[1]: Started
frigate_alert.service.
déc. 07 12:20:43 ultra.kervao.fr mosquitto[1436264]:
1765106443: New connection from 127.0.0.1:55164 on port 1883.
déc. 07 12:20:43 ultra.kervao.fr mosquitto[1436264]:
1765106443: New client connected from 127.0.0.1:55164 as
auto-5B7917FC-A109-8461-E38C-B893A8928EA6 (p2, c1, k60,
u'olivier').
et pour une
détection
déc. 07 19:47:55 ultra.kervao.fr alerte_frigate[1596716]:
[INFO] Detected: camera=Camera-entree, label=person,
id=1765133275.303314-xxsfrt
déc. 07 19:47:59 ultra.kervao.fr
alerte_frigate[1596716]: [DEBUG] Trouvé après 3 seconde(s):
/media/frigate/clips/Camera-entree-1765133275.303314-xxsfrt.jpg
déc. 07 19:47:59 ultra.kervao.fr
alerte_frigate[1596716]: [INFO] Clip annoté trouvé:
/media/frigate/clips/Camera-entree-1765133275.303314-xxsfrt.jpg
déc. 07 19:47:59 ultra.kervao.fr
alerte_frigate[1596716]: [INFO] Clip candidate trouvé:
/media/frigate/clips/Camera-entree-1765133275.303314-xxsfrt.jpg
déc. 07 19:48:00 ultra.kervao.fr
alerte_frigate[1596716]: [INFO] Fichier stable
(taille=223910). Prêt à être envoyé.
Le contenu du mail est le suivant en cas d'alerte
Nouvelle détection Frigate.
Caméra : Camera-entree
Objet : person
ID : 1765133275.303314-xxsfrt
Payload brut :
{"before": {"id": "1765133275.303314-xxsfrt", "camera":
"Camera-entree", "frame_time": 1765133275.303314, "snapshot":
null, "label": "person", "sub_label": null, "top_score": 0.0,
"false_positive": true, "start_time": 1765133275.303314,
"end_time": null, "score": 0.89453125, "box": [832, 201, 907,
368], "area": 12525, "ratio": 0.4491017964071856, "region":
[724, 143, 1044, 463], "active": true, "stationary": false,
"motionless_count": 0, "position_changes": 0, "current_zones":
[], "entered_zones": [], "has_clip": false, "has_snapshot":
false, "attributes": {}, "current_attributes": [],
"pending_loitering": false, "max_severity": null,
"current_estimated_speed": 0, "average_estimated_speed": 0,
"velocity_angle": 0, "path_data": [],
"recognized_license_plate": null}, "after": {"id":
"1765133275.303314-xxsfrt", "camera": "Camera-entree",
"frame_time": 1765133275.499867, "snapshot": {"frame_time":
1765133275.303314, "box": [832, 201, 907, 368], "area": 12525,
"region": [724, 143, 1044, 463], "score": 0.89453125,
"attributes": [], "current_estimated_speed": 0,
"velocity_angle": 0, "path_data": [],
"recognized_license_plate": null,
"recognized_license_plate_score": null}, "label": "person",
"sub_label": null, "top_score": 0.8671875, "false_positive":
false, "start_time": 1765133275.303314, "end_time": null,
"score": 0.84765625, "box": [815, 201, 897, 364], "area":
13366, "ratio": 0.5030674846625767, "region": [716, 134, 1036,
454], "active": true, "stationary": false, "motionless_count":
0, "position_changes": 1, "current_zones": [],
"entered_zones": [], "has_clip": false, "has_snapshot": true,
"attributes": {}, "current_attributes": [],
"pending_loitering": false, "max_severity": null,
"current_estimated_speed": 0, "average_estimated_speed": 0,
"velocity_angle": 0, "path_data": [[[0.6687, 0.5056],
1765133275.499867]], "recognized_license_plate": null},
"type": "new"}
avec l'image de l'instantanée en pièce jointe.
Et voilà
une autre variante avec un envoi avec un mail en
HTML
dans le corps du message
### --- MAIL HTML ---
TMPMAIL=$(mktemp)
cat > "$TMPMAIL" <<EOF
<html>
<body style="font-family:Arial,sans-serif">
<h2 style="color:#c00">🚨 Alerte
Frigate</h2>
<p>
<b>Caméra :</b> ${camera}<br>
<b>Objet détecté :</b> ${label}<br>
<b>ID événement :</b> ${EVENT_ID}<br>
<b>Date :</b> $(date +"%Y-%m-%d %H:%M:%S")
</p>
<p>Snapshot annoté :</p>
</body>
</html>
EOF
s-nail \
-S smtp="$SMTP_URL" \
-S from="$MAIL_FROM" \
-s "Alerte Frigate —
${label} (${camera})" \
-a "$ATTACH" \
-M "text/html" \
"$MAIL_TO" <
"$TMPMAIL"
log "Mail envoyé avec snapshot :
$CLIP_FILE"
rm -f "$TMPMAIL"
Envoi des
alertes avec Signal
On
en vient à
Signal ou
plutôt
signal-cli la version en ligne de commande dont
l'URL est
https://github.comAsamK/signal-cli,
j'ai récupéré le binaire que j'ai décompressé et placé au bon
endroit
tar xvfz signal-cli-0.14.1-Linux-native.tar.gz
mv signal-cli /usr/local/bin
on aura besoin aussi du générateur
qrencode qu'on
installera via
urpmi. On suppose maintenant que vous
disposez déjà d'un compte
Signal, on va lier le poste
Frigate
au compte principal qui est sur le mobile en tapant
signal-cli link -n "FrigateAlert"
cela donne quelque chose comme
█████████████████████████████████████████████████
█████████████████████████████████████████████████
████
▄▄▄▄▄ █▀ ▄▀▄█▄▀ █ ▄█ ▄▄█▄█▀ ██▄ █ ▄▄▄▄▄ ████
████ █
█ █▀█ ▄▀█▄ ▄█▀█▄▄▀▀▄▀▀ ▀▀▄ █ █
█ ████
████
█▄▄▄█ █▀ ▀▀▄▄▄▄▄██▀▄▄█▄▀██ ▄█▄▄██ █▄▄▄█ ████
████▄▄▄▄▄▄▄█▄▀
█ █ █ █▄▀ ▀▄▀ █ █▄█▄▀▄█▄▄▄▄▄▄▄████
████▄
▀▄▄ █▄█ ▀█▀ ▄▄▀ ▄█▄█ █▄ █▀▄ ▀ ▀ ▀
█████
████▄
██▀█▄ ▄ ▀ ▄▄▄ ▀▀▄ ▄▀ ▄█▄▄███ █▀▀█▀▄██████
████
▀█▀ ▄█▀█▄▄▀▀▄▀▄█▀█▄█▄▄▄▄█ ▄▄█▀▀▀▀ █
████
█████▄▀▀
▄▄ ▀▀█▀█ ▄▄▄█▄ █▀ ▄█▄███▀█▄ ▄ ███▀████
████▄█▄▄▄█▄█
▄█▄█▄▄▀█▀▀▄▀ ███▄▄▄▄▀▀▀▀▀▀▀ ▀█████
████▄▀▀▀▀
▄▄▀ ▀█▄█▀▄ █▄█ ▄█ █ ▀▄▄▀▄█▄▄▄████████
████▄▀██▄▀▄██
▄█▄█▀▀▀█▄█▀▀▄ ▀▄▀ ▀ █▀▄▄▀ ▄▄▀▀████
████▀
██▄▄▄ █▄ ▄▄██▀█▀ ▀ ███▄ █▄█ ▀█
███▀████
████
▄▄ ▀▄▄▄▀█ ▄▀ ▀ █ ▀▄▄▄
▀▄▀▀▀▀▀▀▀▄ ▄▀████
████ █▀
█▄▄██ ▀█▄ ▄▄█ ▀█▄ ▄█▀▄█ ▀█▀█▄ ▄▀▄█▄▄▀████
████▀▀▀▀
▀▄▄ ▀▀▄▀▀▄ ▄█▀█▄▀▀▀ ▀▄ ██ █▀█▀ █▄▄ ████
████ █
▀▀▀▄██▄██▀▄█ ▄▄▀█▄ ▀▀▄▄▄██▀█▄███▄ ▄▀▀████
████▄████▄▄█
▀█▀▄▄▀▄▀▄██ ▄▄▄█▄▀ ▄▄█ ▄▄▄ ▀ ▀ ████
████
▄▄▄▄▄ █▄ █ █▀ █▄█▄ ▄▀█▄▄ ▄▄▄ █▄█ ▄▄▀▀████
████ █
█ █ ▀▄▄█▀ ▀█▄█▀ ██▄ ▀▀▀ ▀█ ▄▄▄▄█
████
████
█▄▄▄█ █ █ ▄███▀█ ▀▀▄█ █▀▄███▄▀█▄ ▄ ▄▀█████
████▄▄▄▄▄▄▄█▄▄█▄█▄▄█▄▄█▄▄█▄▄▄█▄▄███▄██▄▄█████████
█████████████████████████████████████████████████
█████████████████████████████████████████████████
sgnl://linkdevice?uuid=ITD32aRGnIGBhZIrHpUFqQ%3D%3D&pub_key=BZ0yldJk5JH04kHEQGm8Ga%1B4b3tSaJUBZXb%2F8K%2Bpdee4
avec le mobile on associe le poste
Frigate
en visualisant le QRCode ainsi obtenu et dans le premier shell
on a comme message
INFO ProvisioningManagerImpl - Received link
information from +336XXXXXXXX, linking in progress ...
Associated with: +336XXXXXXXX
C'est bon le serveur
Frigate est bien associé au compte
Signal principal
Pour voir si ça fonctionne on peut taper
signal-cli --username +336XXXXXXXX send -m "This is a
message" 06YYYYYYYY
Voilà une variante pour envoyer sur un
groupe spécifique où on pourra rajouter d'autres personnes.
Pour lister les groupes on tapera
signal-cli listGroups
voilà le résultat
INFO AccountHelper - The Signal protocol expects that
incoming messages are regularly received.
Id: 2BVGj6gu1es4K9(...)4BdAwavlpon8rE= Name:
groupe1 Active: true Blocked: false
Id: vToJsVzeJeME(...)iyP+Xxf61plZA8= Name: groupe2
Active: true Blocked: false
Id: ZWLvp3vW(....)vYy5hse3hpTQ0= Name: groupe3
Active: true Blocked: false
Id: 9dhS9vM5(...)rVVUJSM/7jYIrIU84= Name: groupe4
Active: true Blocked: false
Id: puoaoo7(...)8hm62WWcMlFqo= Name: groupe5
Active: true Blocked: false
et on met l'id du groupe concerné, pour envoyer un message ça
donnera
signal-cli
--username +336XXXXXXXX send -g
vToJsVzeJeME(...)iyP+Xxf61plZA8= -m "This is a test
message"
maintenant on pourra rajouter en début de script avec les autres
variables
SIGNAL_USER="+336XXXXXXXX"
# ton numéro Signal
SIGNAL_DEST="+336YYYYYYYY"
# numéro qui reçoit les
alertes qui peut être le même numéro, ça apparaitra dans les
Notes perso
puis
plus loin à la place de l'envoi par mail
###
--- ENVOI SIGNAL ---
if [[ -n "$ATTACH" && -f
"$ATTACH" ]]; then
signal-cli \
send
-u "$SIGNAL_USER"\
-g
"Wti9r4I7n+76f(...)O3yLkUIgh3TAt9Y="\
-a
"$ATTACH"\
-m
"🚨 Alerte Frigate
Caméra
: ${camera}
Objet
: ${label}
ID
: ${EVENT_ID}
Date
: $(date)"
# si tmp file,
on peut le supprimer
if [[
"$ATTACH" == /tmp/frigate_snapshot_* ]]; then
rm
-f "$ATTACH"
fi
log "Alerte
envoyée sur Signal au groupe Alarme avec pj : $ATTACH"
else
signal-cli \
send
-u "$SIGNAL_USER"\
-g
"Wti9r4I7n+76f(...)O3yLkUIgh3TAt9Y="\
-m
"🚨 Alerte Frigate
Caméra
: ${camera}
Objet
: ${label}
ID
: ${EVENT_ID}
Date
: $(date)"
log "Alerte
envoyée sur Signal au groupe Alarme sans pj"
fi
Et
voilà ce que ça donne avec un envoi sur mon propre numéro
en cas d'alerte qui ne correspond pas à
person ou car voilà ce que journalctl remontera
déc. 12 18:39:10 ultra.kervao.fr alerte_frigate[3356635]:
[DEBUG] Événement ignoré pour label=cat
Frigate+
Frigate+ est l'option payante de
Frigate qui pour un
abonnement de 50$ (payable via paypal) par an, le principal attrait
de cette version est de pouvoir bénéficier d'un modèle personnalisé
qui permet d'affiner la détection en classant les vrais et faux
positifs et d'accéder également aux modèles de la communauté. A
force d'apprentissage le modèle personnalisé deviendra de plus en
plus précis et nécessitera de moins en moins de ressource.
La page officielle est
https://plus.frigate.video,
une fois l'abonnement payé la première chose à faire est de créer la
clé API puis de créer les caméras.
Dans la configuration de
Frigate maintenant on indiquera la
clé et on activera les photos instantanées (snapshots). Dans le
fichier
docker-compose.yml on rajoute dans la section
environnement
environment:
PLUS_API_KEY: votre-clé-API
dans le fichier
config.yaml on rajoute si ce n'est
pas déjà fait une section
snapshots
snapshots:
enabled: true
timestamp: true
bounding_box: true
retain:
objects:
person: 7
clean_copy: true
Pour
prendre en compte les modifications on stoppera
Frigate en
tapant
docker stop frigate puis
docker compose -f docker-compose.yml up -d
et on relance
Frigate en tapant
docker start frigate et on peut se rendre compte
que
Frigate+ est bien fonctionnel

Maintenant on clique sur Explorer et
dans les filtres, on retient que les objets qui ont un
instantané (snapshot) et qui n'ont pas été encore soumis à la
base centralisée de Frigate+

on clique sur une image d'un objet et puis sur Instantané,
on confirme si l'objet détecté en bas à droite de l'image est
bien identifé

Dans cette copie d'écran on voit un exemple de
classification avec la sous catégorie de l'objet Voiture et la
plaque d'immatriculation qui a été identifiée. L'image a été
soumise à la base
Frigate+.
L'image est soumis au serveur centralisé et ainsi de suite, on
se rend maintenant sous
https://plus.frigate.video/dashboard/images/?tab=0
où on retrouve toutes les images qui ont été soumises. En
cliquant sur une image on retrouve les objets qui ont été
détectés

Assurez-vous que vos boîtes
d'annotation sont bien cadrée autour de l'objet, il
faut éviter de laisser du vide inutile autour de l'objet. Si
une voiture est partiellement cachée par un arbre (comme
ci-dessus), il faut recadrer la boîte sur la partie visible de
la voiture si elle reste reconnaissable, sinon il peut être
préférable de l'ignorer.
Si on est d'accord, on clique sur
Verify & Save

Maintenant si un objet n'a pas été détecté on
peut lui indiquer en cliquant sur Add (w) et on place la
boîte de détection à l'endroit qui va bien en identifiant
clairement l'objet (dans l'image ci-dessous il n'y a personne,
c'est pour l'illustration)

a fortiori s'il y a un faux positif, on cliquera
sur la boîte pour la supprimer et on voit que le label de
l'objet se retrouve barré

On va maintenant générer son modèle personnalisé
en plus du modèle de base de Frigate+ qui est lui même
enrichi et entraîné par les objets identifiés par la communauté.
Pour le créer il faut télécharger au moins dix images qui auront
été correctement annotés et vérifiés, puis on l'enrichit en
continuant à télécharger des images. L'idéal est d'avoir une
bonne centaine d'images dans toutes les configurations météo
pour les caméras extérieures et de luminosité.
Il faut cliquer sur Request Model

J'ai choisi yolov9 qui est réputé
meilleur que mobiledet qui correspond à ma clé TPU

Et voilà le résultat

L'onglet Base Models donne la liste des
modèles de base utilisés par défaut

Une fois que la génération du modèle est achevée qui peut être assez
rapide si on n'a qu'une dizaine d'images téléchargées, on obtient un
identifiant. Ci-dessous il m'en a créé deux.
Je me limite aux modèles pour ma clé TPU et j'indique son
identifiant dans le fichier
config.yaml avec une nouvelle
section
model:
path: plus://id-du-modèle
et on relance Frigate pour que le fichier soit pris en
compte, et voilà ce que ça donne dans l'interface
A partir de là il faudra modifier les réglages de détection
conformément à cette
page. Ensuite on peut constater qu'on capte bien plus
d'objets comme ce chat que je n'arrivais pas à détecter
auparavant
Frigate+ permet de générer
jusqu'à 12 modèles par an, l'intérêt de générer plusieurs
modèles est de générer, modèle après modèle, des modèles affinés
qui s'adaptent précisément à l'environnement des caméras. Les
modèles successifs vont améliorer la détection de faux positifs,
vont s'adapter aux conditions variables (saison, vent,
luminosité, ...), mieux détecter certains objets (animaux, objet
fixe, ...). Générer un modèle supplémentaire ne signifie pas
qu'on utilisera plusieurs modèles jusqu'à saturer les ressources
du système, le nouveau modèle remplacera juste le précédent.
Générer un modèle par mois est un bon
rythme, dans la période de vie d'un modèle, il faudra continuer
à annoter les images, dans l'idéal il faut au moins 200 à 300
images annotées pour que ça vaille le coup de changer de modèle
et qu'on puisse constater une réelle amélioration.
Attention pour l'annotation des images,
dans les images qu'on soumet il ne faut pas se limiter aux faux
positifs sinon le modèle va devenir paranoïaque et ne plus rien
détecter ou de se mélanger les pinceaux dans la détection,
confondre par exemple une personne avec un chat, il faut donc
veiller également à soumettre des détections positives. Le ratio
idéal est de soumettre 80% de vrais positifs et 20% de faux
positifs.
S'il détecte régulièrement un pilier de
portail comme une personne, il faudra soumettre également des
images où une vraie personne passe devant le pilier histoire
qu'il voit la différence, c'est ce qu'on appelle de l'apprentissage
contrastif.
Pour créer un nouveau modèle dans l'interface Frigate+ on
cliquera sur Request Model
Puis
Continue, j'ai choisi le modèle adapté a la clé
Coral
cela va prendre un peu de temps pour le générer
on est averti par mail quand le modèle est prêt
Il faut ensuite modifier le fichier config.yaml pour
indiquer l'identifiant du nouveau modèle et relancer frigate.
model:
path: plus://nouvel-identifiant
et pour vérifier que c'est bien pris en compte, on ira vérifier
les paramètres au niveau de Frigate+
A noter que si le modèle de base évolue vers une nouvelle
version, il faudra redemander la génération d'un nouveau modèle
personnalisé pour qu'il soit pris en compte.
En cas de non reconduction de l'abonnement on pourra toujours
avoir accès aux modèles qui ont été générés.
Quelques liens pour en savoir plus