À propos du projet

UniPlateTracker est un tableau de bord privé et auto-hébergé pour le suivi des plaques d’immatriculation capturées par les caméras UniFi Protect. Il reçoit les événements de détection via des webhooks de l’enregistreur UniFi, les enregistre dans une base de données PostgreSQL, et les présente via une interface web pour la visualisation, la recherche et l’analyse de l’activité des véhicules. Les miniatures et les fichiers vidéo restent sur le serveur de l’utilisateur, avec une intégration optionnelle à la DVLA britannique comme seule source de données externe décrite. Fonctionnalités : - Traitement en temps réel des événements : les détections de plaques arrivent via des webhooks UniFi Protect et sont traitées immédiatement. - Capture vidéo à la demande : un worker Node.js autonome enregistre un court clip pour chaque détection à partir du flux RTSP de la caméra, avec une gestion de la mise en mémoire tampon avant et après l’événement par un processus séparé. - Intégration optionnelle à la DVLA (Royaume-Uni) : récupération des détails du véhicule tels que la marque, la couleur, le statut de la taxe et du MOT. Un mode international désactive les fonctionnalités spécifiques au Royaume-Uni, permettant à l’application de fonctionner dans d’autres régions, bien que les plaques non britanniques afficheront « Inconnu » à moins que ENABLE_INTERNATIONAL_API ne soit configuré. - Tableau de bord d’administration : une zone protégée avec des graphiques et des statistiques d’utilisation, ainsi que des comptes d’administration hiérarchiques où l’administrateur initial peut accorder ou révoquer l’accès à d’autres administrateurs ; ces actions sont enregistrées dans un journal d’audit pour examen. - Table des détections : dense et triable, conçue pour une lecture rapide. Le tri et le filtrage sont effectués dans la base de données, de sorte que l’ordre s’applique à l’ensemble des résultats plutôt qu’à la page actuelle, et le tableau se transforme en une liste de cartes sur les écrans étroits. - Mise en évidence du statut : les véhicules taxés avec un MOT valide restent visuellement neutres, tandis que les véhicules expirés, non taxés ou SORN sont mis en évidence ; « pas d’enregistrement DVLA » est affiché comme un badge distinct creux et pointillé, de sorte que l’absence d’information ne soit jamais confondue avec un résultat propre. - Accessibilité : contrôles étiquetés, tri et pagination au clavier, aria-sort sur le tableau, et prise en charge de prefers-reduced-motion. Le projet indique avoir été audité avec zéro violation. Le mode clair et le mode sombre suivent les préférences du système. Pile technologique : Next.js 16 (App Router) avec TypeScript, React 19, Tailwind CSS v4 et shadcn/ui ; routes API Next.js aux côtés d’un worker/gestionnaire de mémoire tampon Node.js autonome ; PostgreSQL pour le stockage ; FFmpeg pour le traitement vidéo ; intégrations avec les webhooks UniFi Protect et l’API DVLA. Étant donné que Tailwind v4 prend son thème à partir du CSS, il n’y a pas de tailwind.config.ts — les tokens de conception, les styles de plaques et de statut se trouvent dans le bloc @theme de src/app/globals.css. Déploiement : La configuration de base documentée est Debian 12 avec une caméra UVC-AI-Pro (version 5.1.57) et UniFi Protect 9.4.19, avec la note que d’autres configurations devraient fonctionner. Deux méthodes sont décrites : - Installation manuelle : installer Node.js 20+, PostgreSQL et FFmpeg ; copier le fichier d’environnement d’exemple en .env.local et remplir les valeurs telles que POSTGRES_URL et SESSION_SECRET ; créer les répertoires de mémoire tampon et de capture finale si la capture vidéo est activée ; installer les dépendances pour l’application et le worker ; exécuter npm run db:init pour créer les tables et enregistrer le premier e-mail d’administrateur ; construire et démarrer l’application, en l’optionnant pour la rendre persistante avec PM2. - Docker : télécharger le fichier compose et le modèle d’environnement, le renommer en .env.local, fournir POSTGRES_URL, SESSION_SECRET et NEXTAUTH_URL (en utilisant l’IP réseau du serveur plutôt que localhost), exécuter un conteneur unique pour initialiser la base de données et créer le premier administrateur, puis tirer et démarrer avec Docker Compose. L’interface web est documentée sur le port 3000 et le point de terminaison du webhook sur le port 4000. Dans UniFi Protect, une alarme est créée sous Paramètres > Système > Autres paramètres > Gestionnaire d’alarmes, déclenchée sur ID > LPR pour les véhicules inconnus et connus, limitée aux caméras LPR, et pointée vers l’URL /webhook de l’application avec les miniatures activées. Notes de dépannage du README : Les détections peuvent afficher « Pas de clip » parce que la détection et la capture sont des chemins séparés : le webhook écrit la ligne tandis que le worker enregistre à partir de RTSP, donc la capture peut échouer pendant que les détections continuent d’arriver. Les vérifications suggérées sont la date du fichier le plus récent dans VIDEO_FINAL_CAPTURE_PATH, si FFmpeg est toujours installé et à son chemin attendu, si les informations d’identification de la caméra ou l’URL RTSP sont toujours valides, si les deux processus d’arrière-plan sont en vie, et si l’utilisateur exécutant l’application peut lire le répertoire de capture. Une tuile « Pas de clip » en pointillés signifie qu’un clip était attendu mais manquant, tandis qu’une icône de caméra simple signifie que la détection n’en a jamais fait référence. Les demandes de vidéo et de miniature renvoient 4004 à moins que les noms de fichiers ne contiennent uniquement des lettres, des chiffres, des points, des tirets et des traits de soulignement avec des extensions .mp4 ou .jpg, et tout chemin qui change lors de la normalisation est refusé, de sorte que le parcours de répertoire échoue plutôt que de s’échapper du répertoire de capture. Les détails du véhicule affichant « Inconnu » signifient que la DVLA ne détient aucun enregistrement pour cette immatriculation ou que la recherche a échoué.