Tuto : Intégrer Frigate, et faire de la reconnaissance video d'objet par IA en local dans son Jeedom

Bonjour à tous,

ca fait quelques semaines que je m’amuse avec un nouvel outil (pour moi, mais sans doute que certains connaissent déjà !), et je me suis donc amusé à intégrer ceci à mon jeedom.

Frigate, c’est quoi : un NVR - Network Video Recording - qui va donc gérer l’ensemble de vos flux vidéo en provenance de vos cameras. une fois bien paramétré, il va faire office de passerelle vidéo entre vos caméras et votre Jeedom, il permet :

  • de récupérer des flux video en rstp, mjpeg, webRTC
  • de récupérer des snapshots
  • de récupérer toutes les infos de detection … plus aucune intelligence dans la camera, il se charge simplement de transmettre les images
  • de piloter ces camera via OnVIF (version 13 en beta au 09/12/2023)

En standard, Frigate integre un moteur d’IA tensorflow qui tourne dans sa version Light sous un RPI4 (c’est mon cas, avec 4 caméras. C’est un peu juste mas ca passe). Je suis en attente de reception d’une clé google coral pour améliorer tout ca.
Au programme, on definit coté Frigate, des masques, des zones, des objets à reperer, et il se charge du reste :

  • Detection des objets en temps reel (avec un pourcentage de correspondance)
  • enregistrement d’une video, debutant X min avant et se terminant x minutes après la detection de l’objet dans la zone
  • enregistrement de snapshots
  • transmission d’alertes à Jeedom en MQTT (de type nouvelle alerte, mise à jour de l’alerte, fin de l’alerte)

  • En jaune, la zone de detection de « personnes »
  • En orange, la zone de detection de « vehicules »
  • En rouge, une zon eou un mouvement a été detecté (puis analysé par tensorflowLite, pour definir si il reconnait quelquechose

Bref, c’est un bonheur. Une fois la camera connectée, on ne retourne plus la voir. tout se passe dans Frigate

Je ne détaillerais pas l’installation, c’ets très bien expliqué, tout se fait en docker : Installation | Frigate
Coté paramétrage : rien de compliquer pour commencer. Le point le plus important est de commencer par paramétrer ces caméras en mode restream coté Frigate, il faut juste bien paramétré les bons streams dans l’entrée go2rtc (cf mon fichier de conf).
Chez moi, j’ai paramétré 2 streams pour chaque caméra :

  • Un stream principale (resolution maximal)
  • Un stream secondaire (sub) pour la detection

La detection se fait sur le stream secondaire, mais l’enregistrement sur le stream principal.
Ma config go2rtc pour ceux que ca interesse

Config go2rtc dans la config frigate
go2rtc:
  streams:
    rtsp_allee:
    - rtsp://jeedom:xxxx@192.168.8.243:88/videoMain
    - ffmpeg:rtsp_allee#audio=opus
    rtsp_allee_sub:
    - rtsp://jeedom:xxxx@192.168.8.243:88/videoSub
    - ffmpeg:rtsp_allee_sub#audio=opus
    rtsp_appentis:
    - rtsp://jeedom:xxxx@192.168.8.242:88/videoMain
    - ffmpeg:rtsp_appentis#audio=opus
    rtsp_appentis_sub:
    - rtsp://jeedom:xxxx@192.168.8.242:88/videoSub
    - ffmpeg:rtsp_appentis_sub#audio=opus
    rtsp_piscine:
    - rtsp://jeedom:xxxx@192.168.8.240:88/videoMain
    - ffmpeg:rtsp_piscine#audio=opus
    rtsp_piscine_sub:
    - rtsp://jeedom:xxxx@192.168.8.240:88/videoSub
    - ffmpeg:rtsp_piscine_sub#audio=opus
    rtsp_salon:
    - rtsp://jeedom:xxxx@192.168.8.241:554/videoMain
    - ffmpeg:rtsp_salon#audio=opus
    rtsp_salon_sub:
    - rtsp://jeedom:xxxx@192.168.8.241:554/videoSub
    - ffmpeg:rtsp_salon_sub#audio=opus

ce sont ensuite les flux go2rtc qui sont utilisés dans frigate ou dans jeedom

Je ne vais pas detailler mon paramétrage de frigate, c’ets propre à chaque config, mais je vous le mets à titre d’info :

Config frigate
mqtt:
  enabled: true
  user: frigate
  password: hNWv9duV5baCN5hjTTdYW2
  host: 192.168.8.200
  port: 1883

ffmpeg:
  hwaccel_args: preset-rpi-64-h264 #Enable Hardware Acceleration
  global_args: -hide_banner -loglevel error -threads 3
  output_args:
    # Optional: output args for detect streams (default: shown below)
    detect: -threads 3 -f rawvideo -pix_fmt yuv420p
    # Optional: output args for record streams (default: shown below)
    record: preset-record-generic
  retry_interval: 10

logger:
  default: info
  logs:
    frigate.mqtt: info

birdseye:
  enabled: true
  mode: continuous
  width: 1280
  height: 720
  quality: 4

model:
  width: 320
  height: 320
  labelmap:
    0: person
    1: vehicle
    2: vehicle
    3: vehicle
    5: vehicle
    7: vehicle
    16: animal
    17: animal
    18: animal
    19: animal
    20: animal

record:
  enabled: true
  retain:
    days: 30
    mode: active_objects
  events:
    pre_capture: 5
    post_capture: 5
    retain:
      default: 30
      mode: active_objects
#      mode: motion

snapshots:
  enabled: true
  clean_copy: true
  timestamp: true
  bounding_box: true
  crop: false
  retain:
    default: 15

detect:
  fps: 5
  width: 1280
  height: 720

go2rtc:
  streams:
    rtsp_allee:
    - rtsp://jeedom:xxxx@192.168.8.243:88/videoMain
    - ffmpeg:rtsp_allee#audio=opus
    rtsp_allee_sub:
    - rtsp://jeedom:xxxx@192.168.8.243:88/videoSub
    - ffmpeg:rtsp_allee_sub#audio=opus
    rtsp_appentis:
    - rtsp://jeedom:xxxx@192.168.8.242:88/videoMain
    - ffmpeg:rtsp_appentis#audio=opus
    rtsp_appentis_sub:
    - rtsp://jeedom:xxxx@192.168.8.242:88/videoSub
    - ffmpeg:rtsp_appentis_sub#audio=opus
    rtsp_piscine:
    - rtsp://jeedom:xxxx@192.168.8.240:88/videoMain
    - ffmpeg:rtsp_piscine#audio=opus
    rtsp_piscine_sub:
    - rtsp://jeedom:xxxx@192.168.8.240:88/videoSub
    - ffmpeg:rtsp_piscine_sub#audio=opus
    rtsp_salon:
    - rtsp://jeedom:xxxx@192.168.8.241:554/videoMain
    - ffmpeg:rtsp_salon#audio=opus
    rtsp_salon_sub:
    - rtsp://jeedom:xxxx@192.168.8.241:554/videoSub
    - ffmpeg:rtsp_salon_sub#audio=opus

cameras:
  Appentis:
    ffmpeg:
      inputs:
      - path: rtsp://127.0.0.1:8554/rtsp_appentis
        input_args: preset-rtsp-restream
        roles:
        - record
      - path: rtsp://127.0.0.1:8554/rtsp_appentis_sub
        input_args: preset-rtsp-restream
        roles:
        - detect
    detect:
      enabled: true
    live:
      stream_name: rtsp_appentis
    birdseye:
      enabled: true
    motion:
      mask:
      - 664,186,1280,221,1280,0,1280,0,0,0,0,111,0,437
      - 1280,720,1280,215,1122,194,986,720
    objects:
      track:
      - person
      - vehicle
      - animal
    zones:
      terrasse:
        coordinates: 986,720,1035,591,707,509,583,720
        objects:
          - vehicle
      avant:
        coordinates: 0,720,992,720,1076,421,673,386,837,223,589,243,0,437
        objects:
          - person
          - animal
  Allee:
    ffmpeg:
      inputs:
      - path: rtsp://127.0.0.1:8554/rtsp_allee
        input_args: preset-rtsp-restream
        roles:
        - record
      - path: rtsp://127.0.0.1:8554/rtsp_allee_sub
        input_args: preset-rtsp-restream
        roles:
        - detect
    detect:
      enabled: true
    live:
      stream_name: rtsp_allee
    birdseye:
      enabled: true
    objects:
      track:
      - person
      - vehicle
      - animal
    motion:
      mask:
      - 324,0,330,49,687,49,708,0
    zones:
      allee:
        coordinates: 1280,720,615,720,0,720,120,453,354,102,523,123,468,229,510,342,631,433
        objects:
        - vehicle
      tout_aee:
        coordinates: 0,0,758,0,1280,140,1280,720,0,720
        objects:
        - person
        - animal
  Salon:
    ffmpeg:
      inputs:
      - path: rtsp://127.0.0.1:8554/rtsp_salon
        input_args: preset-rtsp-restream
        roles:
        - record
      - path: rtsp://127.0.0.1:8554/rtsp_salon_sub
        input_args: preset-rtsp-restream
        roles:
        - detect
    detect:
      enabled: true
      fps: 5
      width: 640
      height: 360
    live:
      stream_name: rtsp_salon
    birdseye:
      enabled: true
    onvif:
      host: 192.168.8.241
      port: 888
      user: jeedom
      password: nadege08
    objects:
      track:
      - person
  Piscine:
    ffmpeg:
      inputs:
      - path: rtsp://127.0.0.1:8554/rtsp_piscine
        input_args: preset-rtsp-restream
        roles:
        - record
      - path: rtsp://127.0.0.1:8554/rtsp_piscine_sub
        input_args: preset-rtsp-restream
        roles:
        - detect
    detect:
      enabled: true
    live:
      stream_name: rtsp_piscine
    birdseye:
      enabled: true
    motion:
      mask:
      - 590,87,1280,121,1280,0,276,0
      - 764,527,996,240,664,192,280,366
    objects:
      track:
      - person
      - animal

Une fois votre frigate opérationnel et le flux MQTT configuré vers votre jeedom, le plus dire est fait

1- on crée des équipements pour gérer la détection avec plugin-jmqtt
Voilà ce que ca donne :


Un équipement par camera permettant d’activer ou desactiver la detection, et les status de detection pour la caméra
Un équipement Event qui remonte le dernier evenement (toute camera confondue
Un équipement pour gerer le serveur (très succinct chez moi)
Je vous les modèles jmqtt des equipememnt (je laisse @bad juger de l’interet de l’integrer dans les templates jmqtt

Frigate_Serveur.json.txt (7,5 Ko)
Frigate_Events.json.txt (10,8 Ko)
Frigate_Camera.json.txt (19,0 Ko)

Voilà, vous avez toutes vos remontées d’evenement et la gestion de vos detections dans Jeedom

2 - pour avoir les images/videos dans son jeedom
Rien de plus simple, on paramètre une camera via le plugin-camera
avec comme adresse ip l’adresse de votre serveur frigate
comme port, le port du serveur frigate (5000 par défaut)
et les différentes adresses de flux

**3 - et pour finir, les notifications sur le salertes avec envoi d’un snapshot horodaté, ainsi que la zone de détection et le niveau de fiabilité de la detection
Un simple scénario (en bloc code) sur declencheur de la modification de la commande info events (équipement events). Ce bloc code envoie une notif à plugin-jeedomconnect


Vous constaterez en regardant la photo que la zone de detection est entourée et il est indiqué le type de detection (personne) et le tx de « justesse »

Dans le bloc code, je ne notifie que sur un évènement de type new et end. Je filtre les évènement de type update.

  • new = arriver d’un objet dans la zone
  • end = sortie de l’objet de la zone
  • update = déplacement de l’objet à l’intérieur de la zone
Bloc code de notification sur detection
$scenario->setLog('┌──────────── Logs bloc code - version du '.$version);

// Variables
$urlFrigate = 'http://127.0.0.1:55000' ;
$eqLogicEventId =  eqLogic::byString('#[Frigate][Events]#')->getId() ;
$destinationPath = '/var/www/html/data/events';
$cmdNotifJC = cmd::byString('#[Norbert][JC_Norbert][Notif_Caméra]#') ;

// Vérifier si le répertoire existe
function createDir($destinationPath,$scenario) {
  if (!is_dir($destinationPath)) {
    // Créer le répertoire s'il n'existe pas
    if (mkdir($destinationPath, 0777, true)) $scenario->setLog('Répertoire créé avec succès : ' .$destinationPath );
    else $scenario->setLog('Erreur lors de la création du répertoire : ' . $destinationPath);
    }
}

function recupFile($sourceUrl,$eventId,$destinationPath,$scenario) {
  $fileContent = file_get_contents($sourceUrl);

  $localFileName = $eventId.'.png';
  $destinationFile = $destinationPath .'/'. $localFileName ;
  imagepng(imagecreatefromstring($fileContent),   $destinationFile );
      
  if ( $fileContent !== false) {
    // Sauvegarder le fichier localement
    
    file_put_contents($destinationFile, $fileContent);
    $scenario->setLog('| Fichier recupéré et redimensionné : '.$destinationFile);
    
    return $destinationFile ;
  } else {
    $scenario->setLog('| Impossible de récupérer le fichier depuis l\'URL '.$sourceUrl);
    return 0 ;
  }
}

function chmodAll666($dir) {
  $files = scandir($dir);
  foreach ($files as $file) {
    if ($file != '.' && $file != '..') {
      $path = $dir . DIRECTORY_SEPARATOR . $file;
      chmod($path, 0666);
    }
  }
}
//Programme principal

// Recupération de l'EventID de l'evenement
$eventId = cmd::byEqLogicIdCmdName($eqLogicEventId,'ID')->execCmd() ;
$camera = cmd::byEqLogicIdCmdName($eqLogicEventId,'Camera')->execCmd(); 
$timestamp = cmd::byEqLogicIdCmdName($eqLogicEventId,'Timestamp')->execCmd() ; 
$label = cmd::byEqLogicIdCmdName($eqLogicEventId,'Label')->execCmd() ; 
$type = cmd::byEqLogicIdCmdName($eqLogicEventId,'Type')->execCmd() ; 
$Score = cmd::byEqLogicIdCmdName($eqLogicEventId,'Score')->execCmd() ; 

$scenario->setLog('| Evenement : '.$eventId);
$scenario->setLog('| Lieu      : '.$camera);
$scenario->setLog('| Date      : '.date('d/m H:i:s',$timestamp));
$scenario->setLog('| Label     : '.$label.' ('.$Score.'%) - Type : '.$type );

if ( $type != 'update' ) {
 
  $sourceUrl = $urlFrigate.'/api/events/'.$eventId.'/snapshot.jpg?bbox=1&timestamp=1';

  createDir($destinationPath,$scenario) ;
  $destinationFile = recupFile($sourceUrl,$eventId,$destinationPath,$scenario) ;
  
  if ( $destinationFile != '0' ) {
    // Modificaiton des droits sur les fichiers
    chmodAll666($destinationPath) ;
    
    // Envoi notification
    $cmdNotifJC->execCmd($options = array('title' => 'title='.$camera.' Detecion mvt | files='.$destinationFile, 'message' => 'Heure : '.date('d/m H:i:s',$timestamp).'<br>Type : '.$label.' ('.$Score.'%) - Etat : '.$type), $cache   = 0);
    $scenario->setLog('| Envoi de la notification avec le fichier '.$destinationFile);
  }
  else {
    $cmdNotifJC->execCmd($options = array('title' => 'title='.$camera.' Detecion mvt', 'message' => 'Heure : '.date('j/m H:i:s',$timestamp).'<br>Type : '.$label.' ('.$Score.'%) - Etat : '.$type), $cache   = 0);
    $scenario->setLog('| Envoi de la notification sans fichier ');
  }
}
$scenario->setLog('└───────────────────────────');

Et voilà une belle intégration pour un bel outil et votre Jeedom équipé d’une reconnaissance d’objet sur vos cameras.
Autre avantage, tout ajout de nouvelle caméra se fait en 10min coté Jeedom ensuite

A noter que j’utilise la version 13 en beta6 (au 09/12/2023) qui integre donc la gesiton des snapshots et du PTZ via onvif :
repo : Releases · blakeblackshear/frigate · GitHub
doc : https://deploy-preview-6262--frigate-docs.netlify.app/

Norbert

22 « J'aime »

Super tuto mais ça fait des mois que j’essay d’installer le container ça bugue tout le temps malgré le suivie de l’explication frigate
Le.container ne veut jamais demaré.
Je vais retester encore

C’est sans doute un PB lié aux répertoires de données ou de config … Pas les bon droits ou le rep n’existe pas. Tu as quoi dans ton docker compose ?

Bravo pour le tuto mais juste le mot « docker » me fait peur pour une eventuelle installation sur mon miniPC :frowning:

Quand tu dis:

Cela veut dire que Frigate ajoute sa propre surcouche logicielle sur l’image de la caméra et fait de la detection ? Meme si la caméra le propose ou ne le propose pas ?

Merci

Perso j’utilise ZoneMinder qui propose approximativement les mêmes fonctions (il n’a pas de reconnaissance IA en natif, mais un add-on que je n’ai pas encore essayé le permet)
Pour ceux qui connaissent les deux solutions : Est-ce que Frigate est « mieux » ?

Il y a des tuto pour des installations from scratch sur le net si nécessaire… Après, ce n’est effectivement pas du plug and play pour celui qui n’y connait rien en informatique.

C’est bien ça. Frigate récupère un flux vidéo brut, et est capable de rediffuser ce flux et de l’analyser pour faire de la détection. C’est carrément plus performant que l’analyse qui est faite dans mes différentes caméras foscam.

Norbert

Zone minder est loin derriere !
En plus d’une usine a gaz qui demande pas mal de ressource, il est souple comme du beton.

Et avoir ses cameras reellement fonctionnelles cest un art.
Sans parler du language de prog utilisé…

Bref pour moi zm c hasbeen

J’ai jamais eu trop de problèmes pour faire fonctionner mes camera avec ZoneMinder. Mais si Frigate est mieux, faut que je fasse un essais.
C’est exclusivement du docker, ou on peut faire tourner ça sur une machine dédiée ?

Chez moi, c’est un docker sur machine dédiée :wink:

C’est un drôle de concept que de devoir obligatoirement passer par un docker même sur une machine dédié…
Et perso rien que le docker-compose me fait perdre mes cheveux rien que d’en parler !

Non, ça évite de gérer de multiples plateformes, multiples niveaux d’os, multiples dépendances.
Idem côté maj, on est sur de pas tout casser à la première maj d’os ou applicative
Docker ne signifie absolument pas pas plusieurs applications sur une même machine. Par contre, ça facilite ce genre de chose, car du coup chaque appli est indépendante de celle d’à côté

Norbert

1 « J'aime »

Ok je comprend.
Faut que j’essaye, j’ai vu qu’on trouve des tutos sur le net pour tout installer de zéro pour les noobs comme moi.
Sur la machine qui me sert actuellement à faire tourner ZM (un PC HP a base de Pentium G) j’ai un port M.2 « wifi » de libre, et si j’arrive à faire tourner Frigate je pousserais bien le test jusqu’à mettre un module Coral dessus. Quelqu’un à déjà fait ?

Bonjour,

je m’y suis remi sur la création du contrainer pour frigate mais j’ai toujours l’erreur à la fin que frigate ne veut pas démarre

quand je regatde les log sur portainer du container quand je le démare

      
 * Starting nginx nginx
   ...done.
Error parsing config: [Errno 2] No such file or directory: '/config/config.yml'
 * Starting nginx nginx

pourtant fichier config existe

image

Oui enfin là on s’eloigne du forum.
On va pas se mettre a depanner dautres teucs que jeedom

Y a des forums dédiés pr ca

En plus un ls ok mais on sait jrs pas les droits du fichier et si ca se trouve c ca.

Mais bon je le redis on est pas la pour de l assistance sur frigate docker ou autre.

Ok pas de problème
Je n’en parle plus

Pour moi qui utilise MotionEyeOS (VM dédiée sous Promox) quel serait le plus grand intérêt de Frigate ?

Je ne sais pas trop, je ne connais pas motionEye …
Peut-être rapidement, une appli qui évolue (dernière version de motionEye de 2020), le MQTT et son integraiton à Jeedom), l’intégration native de TensorFlowLite, la possibilité de faire du REstream.
(mais comme je ne connais pas, peut-etre que tout ca existe coté motionEye

Pour moi, les 3 grosses plus-values de Frigate, sont :

  • le MQTT → COM avec Jeedom très facile
  • le REStream → on s’affranchit de toute communication en directe avec les caméras ensuite
  • TensorFlowLite en natif → IA native, avec possibilité en fonction de la conf matérielle de mettre d’autres moteurs d’IA

Norbert

1 « J'aime »

Capture d’écran du 2023-12-11 14-15-26

:thinking:

3 « J'aime »

c’est quand meme chiant de parler de rien, hein :slight_smile: :slight_smile:

1 « J'aime »

Sophisme de l’homme de paille.
Dans un tuto Frigate parler de comment on installe Frigate ne me semble pas si hors sujet que ça.
Mais soit, n’en parlons plus et continuons donc de parler de rien !

4 « J'aime »