Ctrl K
ComunidadGuías…

README.fr.md

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
*[English](README.md) | **Français***

# blink2video

**Gérez vos caméras Blink depuis un ordinateur, et gardez ce qu'elles filment.**

Blink est pensé pour le téléphone : un clip à la fois, aucune archive, pas
d'équivalent sur ordinateur. Les enregistrements vivent sur la clé USB d'un
Sync Module 2 ou la carte microSD d'un Sync Module XR, effacés à mesure que le
support se remplit, ou dans le cloud de l'abonnement, qui les garde quelques
semaines.

blink2video est le versant manquant. Une interface locale pour voir les caméras
en direct et armer la détection. Et ce que le
téléphone ne sait pas faire : récupérer les clips avant que la rotation ne les
efface, incruster l'heure dans l'image, et les assembler en une vidéo par jour,
par semaine et par mois.

Tout tourne sur votre machine. Rien n'est envoyé ailleurs.

L'interface web n'écoute que sur `127.0.0.1` : rien d'autre sur votre réseau
local ne peut l'atteindre, seulement cette machine. Elle n'a pas de mot de
passe propre au-delà de la session du compte Blink : quiconque a accès à
cette machine peut donc l'ouvrir.

## Présentation vidéo

[![Voir la présentation de blink2video : Blink sur votre PC, direct et archives](https://i.ytimg.com/vi/V2E4m_SLgb4/hqdefault.jpg)](https://www.youtube.com/watch?v=V2E4m_SLgb4)

**[Voir la présentation française sur YouTube](https://www.youtube.com/watch?v=V2E4m_SLgb4)** :
3 min 10 s, avec sous-titres et sans voix off. Découvrez pourquoi blink2video
existe, le direct et les archives, puis l'installation sous Windows, le premier
lancement et les principaux réglages.
[English version](https://www.youtube.com/watch?v=6rNqLI9K8Tc).

## Fonctionnalités

- Visionnage du direct de n'importe quelle caméra dans le navigateur, armement
  du système ou d'une seule caméra.
- Son de la caméra dans le direct et les enregistrements (Réglages → Vidéo),
  en sourdine au démarrage avec contrôle d'écoute partagé par page.
- Enregistrement du direct à la demande, un clic pendant le visionnage :
  conservé dans sa propre archive, consultable et filtrable exactement comme
  les clips de détection (écarter, supprimer, filtre caméra et période).
- Photo à la demande, un clic depuis la vignette du direct ou déclenchée à
  distance via une URL webhook (domotique, bouton connecté) : conservée dans
  Photos, consultable et supprimable depuis la page.
- Webhook sortant facultatif (Réglages) : un simple POST HTTP avec le nom de
  la caméra et le chemin du fichier, envoyé une fois qu'un clip ou une photo
  a vraiment fini d'être écrit, pour n'importe quel outil de domotique qui
  sait déjà en recevoir un.
- Téléchargement incrémental des clips de détection de mouvement depuis le
  stockage local du module (clé USB du Sync Module 2 ou carte microSD du XR) et
  depuis le cloud de l'abonnement, sans jamais rapatrier deux
  fois le même enregistrement.
  L'historique des clips traités est conservé à côté de `Blink_Clips` : purger
  ce dossier ne déclenche pas leur téléchargement ni une nouvelle notification.
- Affichage de l'état des caméras : batterie, température, signal, modèle et
  micrologiciel de chaque caméra.
- Incrustation de la date et heure dans l'image, donc conservée par n'importe
  quel lecteur. Taille, couleur, opacité du bandeau et heure sur 24 h ou
  12 h (AM/PM) configurables.
- Création d'une vidéo par jour, par semaine ISO et par mois, pour chaque
  caméra.
- Possibilité d'écarter les clips sans intérêt d'un clic, mis de côté plutôt
  que supprimés, et jamais retéléchargés.
- Surveillance continue et alerte : caméra hors ligne, batterie faible,
  détection coupée, ou rien d'enregistré depuis deux jours. Alerte à acquitter,
  sourdine par caméra.
- Français et anglais partout : interface web, notifications, et la sortie
  console de chaque commande. Détecté depuis le navigateur, changeable
  depuis la page.
- Logiciel autonome pour Windows, Linux et macOS, ffmpeg inclus.

## Captures d'écran

![L'onglet Direct](Screenshots/serve_direct.fr.PNG)

Le Direct : une tuile par caméra, sa dernière vignette, l'armement du système et
de chaque caméra, la batterie, la température, le signal et la date du relevé.
Une caméra hors ligne continue d'annoncer ses dernières valeurs connues, et
l'interface dit de quand elles datent.

![Enregistrer le direct](Screenshots/direct_record_fr.PNG)

Le bouton Enregistrer, en cours d'enregistrement (« Arrêter l'enregistrement »,
en rouge) : un clic pour commencer à sauvegarder le direct dans `Blink_Direct`,
un clic pour arrêter. Les enregistrements apparaissent dans Directs
Enregistrements, consultables et filtrables exactement comme les clips de
détection.

Pour inclure le son de la caméra dans le direct et les enregistrements,
activez **Réglages → Vidéo → Inclure le son de la caméra dans le direct et
les enregistrements**. Cette option est désactivée par défaut et concerne les
nouvelles sessions. Avec le son, le direct utilise le mode compatible MSE,
qui peut démarrer plus lentement. Utilisez **Écouter/Couper le son** dans le
direct ou le volume du lecteur des vidéos sauvegardées. Si le canal principal
reste silencieux, essayez **Alternatif** dans les réglages. Sans piste audio,
la vidéo reste lisible.

La lecture commence en sourdine. Activer le son d'une vidéo conserve ce choix
et le volume pour les autres vidéos de la même page, y compris les lecteurs
recréés pendant le défilement. Changer de vue, de page de galerie ou de filtre,
ou recharger la page, remet la lecture en sourdine. La sourdine de lecture ne
change pas le son enregistré. Les anciennes vidéos sans son restent sans son.

![L'onglet Clips](Screenshots/serve0.fr.PNG)

Les clips du plus récent au plus ancien. Chaque carte donne la caméra, la
durée, la date et le modèle, et le bouton « Écarter » retire le clip de
toutes les vidéos assemblées.

![Le panneau de filtre](Screenshots/filtre.fr.PNG)

Un seul bouton Filtre pour la caméra et la période ensemble : préréglages
rapides (aujourd'hui, cette semaine, ce mois-ci, 2 derniers mois, ou tout
l'historique) ou une plage personnalisée à l'heure près, pour retrouver un
incident précis sans défiler tout l'historique d'une caméra toujours armée.
Le filtre choisi reste mémorisé d'une visite à l'autre.

![Le panneau de réglages](Screenshots/settings.fr.PNG)

Les réglages, derrière l'icône engrenage : démarrage automatique à
l'ouverture de session, actualisation automatique de la page, port du
serveur, dossier des vidéos avec un sélecteur natif, et cadence de lecture
du stockage local et du cloud. Aussi l'horodatage incrusté dans l'image
avec sa taille, sa couleur, l'opacité de son bandeau et l'heure sur 24 h
ou 12 h, le fuseau horaire,
le protocole du direct (WebRTC ou MSE), l'archivage
quotidien/hebdomadaire/mensuel activable indépendamment, la mise en
sourdine des alertes par caméra, la suppression automatique après
téléchargement par caméra, et un bouton pour arrêter toute la surveillance
sans passer par le mode CLI.

## Démarrer

**1. Installer.** Téléchargez l'archive de votre système depuis la
[dernière version publiée](https://github.com/nico579/blink2video/releases/latest)
et décompressez-la. ffmpeg voyage dans le bundle, rien n'est installé dans le
système.

| Système | Archive | Premier lancement |
|---|---|---|
| Windows 10/11, x86-64 | `blink2video-windows-x86_64.zip` | `blink2video.exe` depuis un terminal |
| Linux x86-64, glibc 2.35+ (Ubuntu 22.04+, Debian 12+) | `blink2video-linux-x86_64.tar.gz` | `chmod +x blink2video`, puis `./blink2video` |
| macOS 12+, Apple Silicon | `blink2video-macos-arm64.zip` | `xattr -dr com.apple.quarantine blink2video`, puis `./blink2video` |

Les archives embarquent WebRTC, le protocole par défaut du direct. Sous macOS,
ses bibliothèques exigent macOS 14 ou plus : sous macOS 12 et 13, blink2video
démarre normalement et le direct retombe sur MSE.

Windows 7 SP1 x64 dispose d'une [édition legacy séparée](WINDOWS7.md), publiée
aux côtés de chaque [release](https://github.com/nico579/blink2video/releases/latest).
Pour le WebRTC natif, utiliser Supermium 144 R5 ou Thorium Legacy 122, validés
sur les caméras réelles ; conserver MSE avec Firefox ESR 115. Voir le
[tableau des navigateurs testés](WINDOWS7.md#quel-navigateur-utiliser-pour-webrtc-).

**2. Le lancer.** Double-clic sur l'exécutable (ou `./blink2video` depuis un
terminal). Aucun argument nécessaire : sans session valide, un onglet s'ouvre
tout seul sur une page de connexion : votre adresse, votre mot de passe, puis
le code que Blink envoie. Seul un jeton de session est conservé, jamais le mot
de passe.
Lors de la toute première utilisation, le panneau Réglages s'ouvre ensuite
automatiquement. Vérifiez notamment le dossier des vidéos et le fuseau puis
cliquez sur « Appliquer » : aucun clip n'est téléchargé avant cette validation.
La surveillance, le rapatriement des clips et l'assemblage démarrent alors,
chacun à son rythme, et les clips apparaissent au fur et à mesure. Ce parcours
n'est pas répété lorsque le dossier des vidéos est changé.

Si l'onglet ne s'est pas ouvert, ou que vous l'avez fermé, `blink2video open`
le rouvre.

Une icône apparaît aussi dans la zone de notification quand `start` tourne
(Windows/macOS ; sous Linux, selon la prise en charge de votre bureau), avec
Ouvrir/Redémarrer/Arrêter, sans passer par le terminal.

**3. Réglages.** L'icône engrenage, en haut à droite, ouvre un panneau :
démarrer automatiquement à l'ouverture de session, actualiser la page toute
seule à l'arrivée des clips, la fréquence de lecture du stockage local et du cloud,
et un bouton pour tout arrêter. `blink2video autostart on` et `blink2video stop`
font la même chose depuis un terminal, si vous préférez.

<details>
<summary>Depuis les sources, avec Python 3.11 ou plus récent</summary>

```bash
git clone https://github.com/nico579/blink2video
cd blink2video
python blink2video.py login
```

Le premier lancement crée un environnement isolé dans `~/.blink2video/venv` et
s'y relance. `blink2video smoketest` vérifie ensuite que tout fonctionne sur
votre machine.

Le binaire publié n'est ni signé ni notarisé : sous macOS, Gatekeeper refuse le
premier lancement d'une archive téléchargée par un navigateur, d'où le `xattr`
du tableau. Un clic droit puis « Ouvrir » fait la même chose. Si le message
est « Apple n'a pas pu vérifier [...] logiciel malveillant », c'est ce contrôle,
pas une détection réelle de malware : ça signifie juste qu'aucun compte
développeur Apple (99 $/an) n'a signé le binaire.

</details>

<details>
<summary>Avec Docker</summary>

```bash
git clone https://github.com/nico579/blink2video
cd blink2video
docker compose up -d
```

Ou, sans cloner, avec l'image publiée sur
[Docker Hub](https://hub.docker.com/r/nico579dock/blink2video) :

```bash
docker run -d --name blink2video --restart unless-stopped \
  -p 127.0.0.1:8765:8765 -e BLINK_TRUSTED_LOOPBACK_PROXY=1 \
  -v blink_data:/data nico579dock/blink2video
```

Ouvrez `http://127.0.0.1:8765` et connectez-vous de la même façon. Réglages,
session et clips persistent dans un volume nommé (`blink_data`), séparé de
l'image : reconstruire l'image ne perd jamais rien.

Le `docker-compose.yml` fourni publie le port sur `127.0.0.1` uniquement,
comme le binaire par défaut : il n'y a aucune connexion sur le tableau de bord
lui-même, donc rien au-delà de cette machine ne peut l'atteindre sauf à élargir
volontairement la publication du port.

</details>

<details>
<summary>Y accéder à distance (reverse proxy)</summary>

Le tableau de bord n'ayant aucune connexion, le serveur n'accepte que les
requêtes dont l'en-tête `Host` vaut `127.0.0.1`, `localhost` ou `::1`, en plus
d'exiger que la connexion elle-même vienne de cette machine (une vérification
que `BLINK_TRUSTED_LOOPBACK_PROXY=1` assouplit pour le pont Docker ci-dessus,
voir son commentaire dans `docker-compose.yml`). Un reverse proxy sur la même
machine satisfait automatiquement la deuxième condition, mais par défaut il
transmet le `Host` envoyé par le navigateur (son nom public ou son adresse
LAN), pas `127.0.0.1`, et se fait donc refuser avec un 403 tant qu'on ne lui
a pas dit de le réécrire. Un simple relais TCP (`socat`, la redirection de
port d'un routeur) ne peut pas faire cette réécriture : il ne voit jamais les
en-têtes HTTP, donc aucune configuration ne le fera atteindre ce serveur ; il
faut toujours un reverse proxy qui comprend le HTTP.

Le navigateur envoie aussi un en-tête `Origin` dès qu'il fait plus que
charger la page (enregistrer un réglage, arrêter la surveillance, mettre une
alerte en sourdine...), et le serveur le vérifie de la même façon. Un proxy
qui ne réécrit que `Host` laisse `Origin` à l'adresse réellement utilisée par
le navigateur : la page elle-même s'affiche très bien, mais chacune de ces
actions se fait quand même refuser. Les deux en-têtes doivent être réécrits.

Caddy :

```
mondomaine.exemple {
  reverse_proxy 127.0.0.1:8765 {
    header_up Host 127.0.0.1
    header_up -Origin
  }
}
```

nginx :

```
location / {
    proxy_pass http://127.0.0.1:8765;
    proxy_set_header Host 127.0.0.1;
    proxy_set_header Origin "";
}
```

Mettez votre propre authentification (mot de passe HTTP basique, certificat
client, liste d'accès) devant l'un ou l'autre : c'est le proxy qui est
joignable depuis le réseau, blink2video lui-même n'en a toujours aucune.

Avec un VPN maillé (Tailscale, WireGuard) plutôt qu'un nom de domaine public,
la même réécriture s'applique toujours : la vérification ne regarde que
l'en-tête `Host`, jamais la façon dont la connexion est arrivée.

```
http://100.x.y.z:9765 {
  reverse_proxy 127.0.0.1:8765 {
    header_up Host 127.0.0.1
    header_up -Origin
  }
}
```

(`100.x.y.z` est l'adresse Tailscale de cette machine, donnée par
`tailscale ip` ; le `http://` explicite évite que Caddy ne provisionne un
certificat que personne n'a demandé.) Aucune authentification séparée n'est
nécessaire dans ce cas : seuls vos propres appareils sur ce réseau peuvent
même atteindre l'adresse.

Cela veut aussi dire que la réécriture ci-dessus est inutile sur un VPN
maillé : lier blink2video directement à l'adresse du tunnel avec `BLINK_BIND`,
puis régler cette même adresse comme « Hôte de confiance » depuis les
Réglages, ou la passer une fois avec `--trusted-host 100.x.y.z` (conservé
ensuite comme n'importe quel réglage). blink2video accepte alors les
requêtes qui lui sont adressées directement, sans proxy entre les deux. Ne
faites confiance qu'à cette adresse précise, et gardez `BLINK_BIND` sur
elle aussi, jamais `0.0.0.0`, qui accepterait alors le même `Host` depuis le
LAN aussi et annulerait l'intérêt.

L'hôte de confiance accepte aussi tout un sous-réseau en notation CIDR, par
exemple `192.168.1.0/24`, pour un client sans adresse fixe (une machine
Windows en DHCP, par exemple) plutôt qu'un seul pair VPN précis. C'est une
garantie différente, plus large : n'importe quel appareil déjà sur ce
sous-réseau obtient le même accès sans authentification, pas seulement
l'unique machine qu'un tunnel VPN laisserait passer. Raisonnable sur un LAN
domestique de confiance, jamais sur un réseau que vous ne maîtrisez pas
entièrement.

Un hôte de confiance exact (une adresse IPv4 ou un nom, pas un sous-réseau
CIDR) permet aussi d'intégrer la page dans une `<iframe>` depuis cet hôte,
quel que soit le port de la page qui l'intègre, par exemple un tableau de
bord domotique comme ioBroker sur 8081 ou 8082. Sans lui, la page refuse
toujours d'être encadrée
(`Content-Security-Policy: frame-ancestors 'none'`), la défense standard
contre le détournement de clic. Un sous-réseau CIDR ne débloque jamais
cela : il n'y a aucun moyen de désigner « n'importe quel hôte de ce
sous-réseau » dans cette politique. Une adresse IPv6 non plus, cette
politique ne sait pas l'écrire : passez par un nom.

L'hôte de confiance accepte plusieurs valeurs, séparées par des virgules,
pour combiner ces cas : `192.168.1.10, 192.168.1.0/24, mon-pc` autorise le
tableau de bord situé en `192.168.1.10` à intégrer la page, et accepte
l'accès direct depuis tout le sous-réseau et par le nom `mon-pc`. Chaque
entrée doit correspondre à ce que le navigateur envoie réellement comme
`Host` : un nom tapé dans la barre d'adresse arrive tel quel, jamais sous la
forme de l'IP qu'il désigne, donc aucune entrée de sous-réseau ne le
couvre : ajoutez aussi le nom.

</details>

## L'interface

La page, sur `127.0.0.1:8765`, a six vues. Chaque navigateur rouvre la
dernière qu'il a affichée : un écran mural revient au Direct, le navigateur du
bureau aux Clips. Pour distinguer une installation d'une autre, Réglages,
Général, « En-tête de la page » donne un titre et une icône (un émoji),
affichés en haut de la page et dans l'onglet.

- **Direct** : une tuile par caméra, son état, l'armement de la détection, un
  bouton plein écran, un bouton « Réveiller » qui force la caméra à se
  manifester tout de suite pour des relevés (batterie, température,
  vignette) plus frais plutôt que d'attendre son prochain passage prévu, et
  un bouton « Photo » qui fait la même chose mais conserve la photo obtenue
  dans Photos au lieu de la jeter, et rafraîchit du même coup la vignette
  de la tuile (les deux consomment un peu de batterie, jusqu'à deux minutes
  sur une caméra endormie). Un direct s'arrête tout seul : dès que l'onglet
  est fermé ou rechargé, au bout de 5 minutes au plus dans tous les cas (un
  plafond côté serveur, quoi que fasse le navigateur), ou plus tôt si
  « Arrêt auto du direct » est réglé dans les Réglages.
  Les caméras hors ligne viennent en fin de liste dans chaque système, faute
  d'images à y voir.
  Le bouton « Ronde… » montre les caméras l'une après l'autre en plein
  écran, pour un écran mural par exemple : chacune reste le nombre de
  secondes choisi (30 par défaut), compté à partir de sa première image,
  puis la suivante prend sa place, et la ronde recommence. Les caméras hors
  ligne ou masquées sont sautées, on peut en écarter d'autres, et la
  limiter à certaines heures de la journée ; en dehors, elle attend sans
  rien réveiller. Échap ou « Arrêter » y mettent fin. Chaque passage
  réveille la caméra, ce qui use vite une batterie, et tant que la ronde
  tourne, la relève du stockage local (clé USB) attend sa pause ou son
  arrêt, le Sync Module ne relayant qu'une chose à la fois. Ces réglages
  restent dans le navigateur, comme la taille des vignettes. Une ronde qui
  tournait encore à la fermeture de la page repart à sa réouverture, quand
  un écran mural redémarre ou qu'une mise à jour recharge la page ; arrêtée
  à la main, elle ne repart pas. Un navigateur n'accorde le plein écran
  qu'après un clic : une ronde qui repart seule remplit donc la fenêtre.
  Pour un écran mural, lancez Chromium ou Edge en mode kiosque (`--kiosk`),
  la fenêtre est alors l'écran entier.
- **Clips** : du plus récent au plus ancien, avec un aperçu et un bouton
  « Écarter » qui retire un clip de toutes les vidéos assemblées.
- **Journalières, Hebdomadaires, Mensuelles** : les vidéos assemblées. Les
  journalières peuvent aussi être groupées par jour plutôt que par caméra
  (Filtre, « Grouper par »), pour voir ensemble les vidéos de toutes les
  caméras à une même date.
- **Photos** : les photos prises à la demande, de la plus récente à la plus
  ancienne, avec un bouton de suppression. Alimentée par le bouton « Photo »
  du Direct, ou à distance via une URL webhook pensée pour la domotique ou un
  bouton connecté (Réglages, « Photo par webhook », donne l'URL et permet de
  régénérer son secret).

Le bouton Actualiser rapatrie les nouveaux clips et reconstruit les vidéos, en
affichant l'avancement.

<details>
<summary>Photo par webhook, en détail</summary>

`GET /webhook/snapshot?camera=<nom>&token=<secret>` déclenche une photo de la
même façon que le bouton « Photo » du Direct. La réponse est un petit JSON
(`{"ok": true, "fichier": "..."}`, ou `{"error": "..."}`), pas une image :
récupérez la photo elle-même ensuite depuis la vue Photos ou `/api/snapshots`.

Le secret voyage dans l'URL plutôt que dans un en-tête parce qu'aucun des
appelants habituels (Home Assistant, IFTTT, un bouton connecté qui ne sait
faire que du GET) ne peut poser un en-tête personnalisé sur un appel webhook :
c'est le même choix que font leurs propres webhooks. Il est généré une fois,
affiché (et régénérable) dans Réglages, comparé en temps constant à ce qui
est fourni : traitez-le comme un mot de passe, puisque le détenir permet de
déclencher une photo sur n'importe quelle caméra en la nommant. Contrairement
au reste du tableau de bord, cette seule route est volontairement joignable
depuis tout le réseau, puisqu'un hub domotique tourne rarement sur
`127.0.0.1` : gardez-la quand même hors d'internet, un appelant limité au
réseau local est l'usage prévu.

</details>

<details>
<summary>Webhooks d'état et d'armement, en détail</summary>

Deux routes de plus pour les scripts (domotique, un planificateur à vous), avec
le même secret que la photo : un seul à garder en lieu sûr.

- `GET /webhook/status?token=<secret>` répond avec l'état de chaque système et de
  chaque caméra en JSON ; ajoutez `&camera=<nom>` pour une seule caméra. Chaque
  caméra a `name`, `system`, `armed` (sa détection), `online`, `status`, `battery`
  (un statut comme `ok`, pas un pourcentage), `battery_signal`, `voltage`,
  `temperature_c`, `wifi`, `firmware`, `model` et `age_seconds` (l'âge du relevé).
  Les champs sont ceux que Blink donne : une caméra qui n'en rapporte pas un
  (une Mini sur secteur n'a pas de batterie) affiche `null`, et Blink a déjà
  changé de tels champs, donc un script doit tolérer une valeur absente.
- `GET` ou `POST /webhook/arm?camera=<nom>&armed=true&token=<secret>` arme ou
  désarme une caméra ; utilisez `system=<nom>` à la place de `camera` pour un
  système entier. `armed` accepte `true`/`false`, `1`/`0`, `on`/`off`. La réponse
  est `{"ok": true, "requested": ..., "changed": ..., "applied": ...}` avec la
  caméra ou le système tels que Blink les rapporte juste après. `changed` est
  faux s'il était déjà dans l'état demandé (tel que blink2video le connaissait
  avant l'appel) ; `applied` est faux si Blink n'avait pas encore suivi. Une
  caméra hors ligne n'est pas tentée : vous recevez `409` avec son état et un
  message clair, au lieu d'attendre un délai. Un nom inconnu donne `404`, un nom
  porté par deux éléments `409`, un secret absent ou faux `403`.
- Plusieurs caméras en un appel : répétez le paramètre,
  `camera=Garage&camera=Grenier&armed=false`. La réponse est
  `{"ok": ..., "scope": "cameras", "cameras": [...]}` avec un résultat par
  caméra (son propre `ok`, `status_code`, `changed`, `applied` ou `error`),
  toujours avec le statut `200` : une caméra hors ligne ou inconnue n'arrête pas
  les autres, et le `ok` global n'est vrai que si toutes ont réussi.

Traitez le secret comme un mot de passe : le détenir permet maintenant aussi
d'éteindre vos caméras, pas seulement de prendre une photo. Chaque changement
fait par le webhook d'armement est ajouté à `armement-webhook.log` dans le
dossier de données, avec l'adresse de l'appelant. Même conseil que pour la
photo : gardez-le sur votre réseau local.

</details>

<details>
<summary>Webhook de notification, en détail</summary>

Le sens inverse de celui ci-dessus, et sans rapport avec lui : un `POST`
avec un petit corps JSON (`{"camera": "...", "chemin": "...", "type":
"clip"}` ou `"snapshot"`) vers une URL réglée dans Réglages, une fois qu'un
clip ou une photo a vraiment fini d'être téléchargé ou enregistré, jamais en
cours de route. URL vide (par défaut) désactive complètement la fonction.

Au mieux, sans nouvelle tentative : une notification manquée, une URL mal
tapée, ou le point d'arrivée momentanément indisponible n'interrompent ni ne
font échouer le téléchargement qu'elle rapporte. Un simple POST HTTP est le
choix volontaire, puisque c'est ce que Home Assistant, Node-RED, n8n et
compagnie savent déjà recevoir, sans broker MQTT ni écouteur UDP maison à
écrire de votre côté.

</details>

## Être prévenu

Une caméra hors ligne, une batterie qui faiblit, une détection coupée ou une
caméra muette depuis deux jours ouvrent une fenêtre à acquitter. Les alertes ne
se déclenchent que sur un changement : une caméra que vous laissez sciemment
hors ligne ne prévient qu'une fois.

## Mettre à jour

Quand une version plus récente est publiée, l'interface affiche un bouton
**Installer 0.x.y**. Il s'occupe de tout : téléchargement, arrêt, remplacement,
relance des mêmes verbes. La version téléchargée doit d'abord démarrer et
annoncer son numéro ; le dossier entier est alors échangé, et si la nouvelle
version ne tient pas après la relance, l'ancienne est remise en place.

Si une coupure de courant tombe au mauvais moment et que le dossier
`blink2video` a disparu, l'ancienne version attend à côté, sous le nom
`.blink2video.backup-…` : renommez ce dossier en `blink2video` et relancez.
Vos réglages et vos clips n'en dépendent pas, ils vivent ailleurs.

## Où vont les fichiers

```
Blink_Clips/       clips bruts, tels que le module les a enregistrés
Blink_Normalized/  les mêmes avec l'heure incrustée
Blink_Excluded/    les clips écartés, conservés plutôt que supprimés
Blink_Daily/       une vidéo par caméra et par jour
Blink_Weekly/      une par semaine ISO
Blink_Monthly/     une par mois
Blink_Direct/      enregistrements du direct, sauvés à la demande
Blink_Snapshots/   photos à la demande, une par clic Snapshot ou appel webhook
```

Dans `Documents/blink2video` par défaut, ou dans le dossier des vidéos choisi
dans les Réglages. Les réglages, la session Blink et les journaux vivent à
part, dans le dossier de données d'application du système
(`%LOCALAPPDATA%\blink2video` sous Windows,
`~/Library/Application Support/blink2video` sous macOS,
`~/.local/share/blink2video` sous Linux) : une mise à jour ou une
réinstallation n'y touche jamais, et les versions sources et exécutable les
partagent. `BLINK_HOME` réunit tout dans un dossier de votre choix. Depuis une
version 0.13 ou antérieure, le premier lancement y recopie les réglages et la
session, et les vidéos restent où elles sont : le dossier des vidéos pointe
vers elles.

### Les vidéos sur un disque à part

Un dossier choisi dans les réglages n'est créé qu'à ce moment-là. S'il manque
plus tard, parce que le disque n'est pas encore monté au démarrage par exemple,
blink2video ne le recrée pas sur le disque système : les téléchargements
l'attendent et partent dès son retour, l'assemblage saute son tour, et un
bandeau rouge nomme le dossier dans la page. Les réglages restent utilisables
pendant ce temps, et vous pouvez y choisir un autre dossier.

Choisissez un sous-dossier du disque, comme `/export/cam/blink2video`, plutôt
que le point de montage lui-même : un point de montage démonté reste un dossier
vide, que rien ne distingue du vrai. Le dossier par défaut et `BLINK_HOME` se
créent toujours à la demande.

### Ne garder les fichiers qu'un temps

Par défaut, rien n'est jamais effacé. Dans les Réglages, « Conservation »
donne à chaque catégorie son nombre de jours : clips bruts, vidéos
journalières, hebdomadaires et mensuelles, directs enregistrés et photos.
0 veut dire garder toujours. Par exemple, bruts 30, journalières 90,
mensuelles 0 garde un mois de clips bruts, trois mois de journées, et chaque
mois pour de bon.

Les vidéos assemblées sont faites les unes des autres, ce qui impose un
ordre. Une journalière est refaite tant que ses clips bruts existent, une
hebdomadaire ou une mensuelle tant que ses journalières existent : chacune ne
peut donc s'effacer qu'après ce dont elle est faite. Les bruts partent par
journée entière, et seulement une fois la journalière faite ; une journalière
part une fois ses bruts effacés et les hebdomadaires et mensuelles qui la
contiennent présentes ; une hebdomadaire ou une mensuelle part quand il ne
reste plus aucune de ses journalières. Les Réglages refusent un ordre qui ne
tiendrait pas. Directs et photos suivent simplement la date de chaque
fichier.

Le ménage passe avec l'assemblage, toutes les cinq minutes, et seul quand
l'assemblage quotidien est désactivé. Les clips effacés restent dans
l'historique des téléchargements : ils ne sont pas retéléchargés.

<details>
<summary>Comment ça marche</summary>

Le clip normalisé est le pivot. Chaque clip est ré-encodé une fois, l'heure
inscrite dans l'image, puis conservé définitivement. Les vidéos journalières,
hebdomadaires et mensuelles ne sont que des copies de flux de ces segments :
aucun ré-encodage, aucune perte de génération, quelques secondes chacune.

C'est ce qui rend l'ajout d'un clip peu coûteux. Un nouvel arrivant ne ré-encode
que lui-même, à peu près au temps réel : un clip d'une minute coûte une minute,
une seule fois.

L'heure est incrustée dans l'image plutôt qu'ajoutée en piste de sous-titres,
que les téléphones et les messageries ignorent. La conversion de fuseau est
faite côté Python, ffmpeg tournant avec `TZ=UTC0` : la chaîne ne dépend d'aucune
base de fuseaux du système.

Un clip est identifié par sa caméra et son instant d'enregistrement, jamais par
l'identifiant du module : redémarrer celui-ci renumérote tout, et les clips déjà
récupérés reviendraient comme neufs.

</details>

## Limites

- Une caméra hors de portée du module accepte la demande de direct mais n'envoie
  jamais d'image ; l'interface le dit.
- Sous Linux, le ffmpeg d'imageio-ffmpeg est compilé sans libfreetype et ne sait
  pas incruster l'horodatage : `sudo apt install ffmpeg`. L'outil essaie chaque
  ffmpeg trouvé et retient le premier capable d'écrire du texte. Windows et
  macOS n'ont besoin de rien.
- Les notifications empruntent les outils du système : fenêtre native sous
  Windows, osascript sous macOS, notify-send et zenity sous Linux. À défaut, la
  surveillance écrit dans `watch.log` et continue. Sous Windows, l'outil déclare
  son identité de notification au premier envoi, dans
  `HKCU\SOFTWARE\Classes\AppUserModelId\blink2video` : sans elle, le système
  jette les notifications sans rien dire. Supprimer cette clé annule la
  déclaration.
- Rien ne tourne pendant que l'ordinateur est éteint : une caméra qui tombe la
  nuit est signalée à l'ouverture de session suivante.
- Blink refuse certains points d'entrée de son API selon la version de client
  annoncée, avec un « An app update is required ». Le direct et le
  téléchargement fonctionnent aujourd'hui ; rien ne garantit que Blink
  n'étende pas ce refus.
- Blink n'expose aucun moyen de redémarrer un module bloqué : il faut le
  débrancher.
- Pas de version iOS ou Android : le téléchargement continu et l'assemblage
  vidéo ont besoin d'un processus en arrière-plan et de ffmpeg, que ni l'un ni
  l'autre système mobile n'autorise à tourner en tâche de fond. L'interface web
  elle-même n'est qu'une page, en revanche : y accéder depuis un téléphone, une
  tablette ou tout autre appareil du LAN demande soit un reverse proxy devant,
  qui relaie vers `127.0.0.1` avec sa propre authentification et son en-tête
  `Host` réglé en conséquence, soit, sur un VPN maillé du type
  Tailscale/WireGuard, une écoute directe sur l'adresse du tunnel déclarée
  comme hôte de confiance depuis les Réglages (voir « Y accéder à distance »
  plus haut), le même principe que l'opt-in du conteneur Docker. L'interface
  web n'a pas d'identifiant à elle : le serveur intégré refuse donc toute
  requête qui ne vient pas de la machine locale elle-même ni d'un hôte de
  confiance, et régler seul `BLINK_BIND=0.0.0.0` ne l'expose pas au LAN.

## Voisins

D'autres projets touchent au même matériel, et se complètent plus qu'ils ne se
concurrencent :

- [blinkpy](https://github.com/fronzbot/blinkpy) est la bibliothèque d'accès à
  l'API sur laquelle repose tout le reste, celui-ci compris.
- [BlinkCamWindowsDashboard](https://github.com/mikeoverbay/BlinkCamWindowsDashboard)
  offre un tableau de bord web et le téléchargement des clips, depuis le cloud
  uniquement, donc avec un abonnement obligatoire, et sans direct.
- [blinkbridge](https://github.com/roger-/blinkbridge) expose une caméra en RTSP,
  pour l'intégrer à un système de vidéosurveillance existant.
- [blink-live-view](https://github.com/andreiele/blink-live-view) se consacre au
  direct sur le bureau.

blink2video se distingue sur trois points : il lit **les deux** sources, le
stockage local du module et le cloud de l'abonnement, sans jamais rapatrier deux fois le
même enregistrement ; il incruste l'heure dans l'image et assemble une vidéo par
jour, par semaine et par mois ; et il tourne sur les trois systèmes en bundle
autonome, ffmpeg compris.

## Ligne de commande

Tout ce qui précède fonctionne déjà depuis la page web. Ce chapitre couvre
l'alternative terminal : scripter, une machine sans écran, une composition sur
mesure, ou la liste complète des options.

<details>
<summary>Toutes les options</summary>

<!-- verbes:début -->
Une commande, un verbe par action. `blink2video <verbe> --help` donne les options de chacun.

```bash
blink2video login       # se connecter au compte Blink, vérification en deux étapes gérée
blink2video list        # ce que contient le module de synchronisation en ce moment
blink2video download    # récupérer les nouveaux clips avant que la rotation ne les efface
blink2video merge       # normaliser, horodater et assembler jour, semaine et mois
blink2video watch       # contrôler l'état de l'installation et alerter s'il se dégrade
blink2video serve       # servir l'interface web, pour regarder, écarter, voir en direct
blink2video start       # tout lancer avec les réglages recommandés
blink2video open        # ouvrir l'interface web dans le navigateur
blink2video stop        # arrêter l'instance qui tourne en fond
blink2video restart     # arrêter puis relancer avec les réglages actuels
blink2video update      # installer la dernière version publiée
blink2video autostart   # inscrire à l'ouverture de session la commande qui suit
blink2video smoketest   # vérifier que l'installation fonctionne sur cette machine
```
<!-- verbes:fin -->

Les options suivent le verbe : `blink2video serve --port 8899`. Plusieurs verbes
se citent d'affilée, chacun avec les siennes. Ce qui se termine s'enchaîne dans
l'ordre cité, ce qui ne se termine pas tourne à côté : `blink2video download merge`
télécharge **puis** assemble, tandis que `serve`, ou tout verbe muni de `--loop`,
occupe son propre processus jusqu'à `blink2video stop`.

`blink2video <verbe> --help` fait toujours foi ; ce tableau récapitule.

**Racine** : `login`, `list`, `download`. Sans verbe, l'aide s'affiche.

| Option | Effet |
|---|---|
| `--hub NOM` | module de synchronisation à utiliser ; tous si omis |
| `--camera NOM` | ne garder que cette caméra |
| `--since JOURS` | ne garder que les clips des N derniers jours |
| `--output DOSSIER` | destination des clips bruts (défaut `Blink_Clips`) |
| `--overwrite` | retélécharger volontairement les clips déjà traités, même après une purge |
| `--from usb\|cloud\|all` | où chercher les clips : le stockage local (USB ou microSD), le cloud de l'abonnement, ou les deux (défaut) ; `usb` reste le nom historique de l'option |
| `--loop [MINUTES]` | répéter au lieu d'agir une fois (défaut 10) |

**`blink2video merge`** : normalisation et assemblage.

| Option | Effet |
|---|---|
| `--exclude CLIP…` | écarter des clips : le brut part dans `Blink_Excluded`, le segment est effacé, le clip n'est plus retéléchargé |
| `--include CLIP…` | annuler une exclusion : le brut revient et le clip est re-normalisé |
| `--date AAAA-MM-JJ` | limiter à une journée |
| `--camera NOM` | limiter à une caméra |
| `--force` | tout reconstruire même si rien n'a changé |
| `--no-weekly` | ne pas reconstruire les agrégats hebdomadaires |
| `--no-monthly` | ne pas reconstruire les agrégats mensuels |
| `--keep-clips-days N`, `--keep-daily-days N`, `--keep-weekly-days N`, `--keep-monthly-days N`, `--keep-live-days N`, `--keep-snapshots-days N` | conservation par catégorie en jours, 0 garde toujours (défaut) ; voir « Ne garder les fichiers qu'un temps » |
| `--purge-only` | appliquer seulement la conservation, sans rien assembler |
| `--no-timestamp` | ne pas incruster la date et l'heure dans l'image |
| `--preset NOM` | preset libx264, d'`ultrafast` à `veryslow` (défaut `veryfast`) |
| `--crf N` | qualité, 0 à 51, plus bas est meilleur (défaut 21) |
| `--font FICHIER` | police .ttf pour l'horodatage |
| `--font-size N` | taille de l'horodatage en pixels, 8 à 500 (défaut : proportionnelle à la hauteur de la vidéo) |
| `--font-color COULEUR` | couleur de l'horodatage : un nom (`white`, `yellow`...) ou un hexadécimal (`#RRGGBB`, `0xRRGGBB`), éventuellement suivi de `@opacité` (ex. `white@0.8`), défaut `white` |
| `--box-opacity N` | opacité du bandeau derrière l'horodatage, `0.0` (invisible) à `1.0` (opaque), défaut `0.55` |
| `--clock 24h\|12h` | format de l'heure incrustée : `24h` (`14:05:09`, défaut) ou `12h` (`02:05:09 PM`) |
| `--timezone ZONE` | fuseau de l'horodatage (défaut `Europe/Paris`) |
| `--input`, `--output`, `--normalized-output`, `--excluded-output`, `--weekly-output`, `--monthly-output` | emplacements de chaque dossier |

**`blink2video watch`** : contrôler l'état, alerter s'il se dégrade. `--ignore
CAMERA…` met une caméra en sourdine, puis poursuit le contrôle ;
`--unignore CAMERA…` lève la sourdine.

| Option | Effet |
|---|---|
| `--loop [MINUTES]` | répéter au lieu d'agir une fois (défaut 10) |
| `--ignore CAMERA…` | mettre une caméra en sourdine, puis poursuivre le contrôle |
| `--unignore CAMERA…` | lever la sourdine |
| `--test` | déclencher une notification de vérification |
| `--dry-run` | montrer sans notifier ni enregistrer l'état |

**`blink2video start`** : la configuration recommandée, en une commande. Elle
équivaut exactement à :

```bash
blink2video serve  watch --loop 10  download --from all --usb-loop 10 --cloud-loop 1  merge --loop 5
```

Les options données après `start` vont à l'interface, `--port` par exemple.

**`blink2video serve`** : servir l'interface web.

| Option | Effet |
|---|---|
| `--port N` | port d'écoute (défaut 8765) |
| `--open-browser` | ouvrir la page dans le navigateur au démarrage |
| `--hub NOM` | module de synchronisation ; tous si omis |
| `--thumbs DOSSIER` | cache des vignettes, jetable |
| `--timezone ZONE` | fuseau d'affichage |
| les mêmes options de dossiers que `merge` | |

**`blink2video open`** : ouvrir l'interface dans le navigateur, et dire si
personne n'écoute. `--port` si vous l'avez déplacée.

**`blink2video stop`** : arrêter l'instance en cours et tous ses verbes. Sans option.

**`blink2video autostart`** : ce qui se lancera à l'ouverture de session.

| Commande | Effet |
|---|---|
| `autostart on` | inscrire `blink2video start` |
| `autostart on <verbes…>` | inscrire cette commande-là plutôt que le défaut |
| `autostart status` | ce qui est inscrit, et ce qui tourne |
| `autostart off` | retirer l'entrée |

`--dry-run` montre sans rien modifier.

**`blink2video smoketest`** : contrôle de l'installation. `--keep` conserve le dossier
de travail, `--timezone` choisit le fuseau de la vidéo de démonstration.

**Variables d'environnement**

| Variable | Effet |
|---|---|
| `BLINK_HOME` | un seul dossier pour tout : réglages, session et vidéos, sauf si un autre dossier des vidéos est choisi dans les Réglages. À défaut, le dossier de données d'application du système et `Documents/blink2video` |
| `BLINK_BOOTSTRAP` | `auto`, `pip` ou `none` : gestion de l'environnement Python |
| `BLINK_BIND` | adresse d'écoute interne de `serve`, à défaut `127.0.0.1`. Utile pour l'utiliser à l'intérieur du conteneur Docker officiel, derrière une publication `127.0.0.1` et `BLINK_TRUSTED_LOOPBACK_PROXY=1` (voir la section Docker), ou pour l'écouter directement sur une adresse de VPN maillé (Tailscale, WireGuard), la façon la plus simple d'y accéder à distance sans reverse proxy : associez-la à cette même adresse comme « Hôte de confiance » dans les Réglages, ou avec `--trusted-host` en ligne de commande (voir « Y accéder à distance » plus haut). Le tableau de bord n'a aucune authentification : le serveur refuse donc toute requête qui ne vient pas de la machine locale elle-même ni d'un hôte de confiance, régler ceci seul à `0.0.0.0` n'expose pas l'interface au LAN |

</details>

**Premier lancement**, étape par étape plutôt qu'un double-clic :

```bash
blink2video login       # se connecter, une fois
blink2video list         # verifier que ca repond : clips presents sur le module
blink2video start         # meme composition que ce que lance le double-clic
```

**Grammaire.** Trois règles suffisent. Le verbe d'abord, ses options ensuite.
Plusieurs verbes se citent à la suite, chacun avec les siennes. Ce qui boucle
tourne à côté, le reste s'enchaîne dans l'ordre où c'est écrit. Une option
placée avant le premier verbe n'appartient à personne, et est refusée :
`blink2video --loop 5 merge` vous le dira plutôt que de faire quelque chose
d'inattendu.

Les gestes courants :

```bash
blink2video start                  # tout, avec les réglages recommandés
blink2video open                   # ouvrir l'interface dans le navigateur
blink2video stop                   # arrêter l'instance de fond et ses verbes
```

Un passage unique, sans rien laisser tourner :

```bash
blink2video download               # les deux sources, une fois
blink2video download --from cloud  # une seule source
blink2video download merge         # télécharger, puis assembler
blink2video download --since 7 merge   # rattraper une semaine, puis assembler
```

Reprendre une journée, ou écarter un clip :

```bash
blink2video merge --camera jardin --date 2026-08-12
blink2video merge --exclude Blink_Clips/jardin/2026-08/2026-08-12_09-23-21Z_jardin.mp4
```

Composer soi-même, quand le défaut ne convient pas :

```bash
blink2video serve --port 8899                       # l'interface ailleurs
blink2video serve merge --loop 30                   # interface, et assemblage toutes les 30 min
blink2video watch --loop 5 download --from cloud --loop 1   # deux boucles, deux cadences
```

**Démarrage automatique.** La case du panneau de réglages fait ça pour la
composition recommandée ; depuis un terminal :

```bash
blink2video autostart on                    # inscrit « blink2video start »
blink2video autostart status                # ce qui est installé
blink2video autostart off                   # retirer
blink2video autostart on watch --loop 30    # n'inscrire que les alertes, à la place
```

`autostart` n'exécute rien : il inscrit au démarrage la commande qui le suit,
telle que vous l'auriez tapée sans lui. Aucun droit d'administrateur n'est
nécessaire, et `--dry-run` montre ce qui serait fait.

Sous Linux, cette entrée est un service systemd *utilisateur* : il vit avec la
session de cet utilisateur, démarre quand il se connecte et s'arrête quand il
s'en va. Sur un serveur, avec un compte dédié où personne ne se connecte,
activez une fois le « linger », et le service démarre dès l'allumage :

```bash
sudo loginctl enable-linger blink2video     # le compte qui le fait tourner
```

Nul besoin pour cela d'une unité système, ni de rien faire tourner en root. Un
compte ouvert par `su` ou `sudo` convient aussi : `autostart on` retrouve seul
son instance systemd, et le signale quand il n'y en a pas encore.

<details>
<summary>Le faire soi-même, sans passer par <code>autostart</code></summary>

**Windows**, un raccourci dans le dossier de démarrage :

```powershell
$s = (New-Object -ComObject WScript.Shell).CreateShortcut(
  "$([Environment]::GetFolderPath('Startup'))\blink2video.lnk")
$s.TargetPath = "C:\path\to\blink2video.exe"; $s.Arguments = "blink2video start"
$s.WorkingDirectory = "C:\path\to"; $s.Save()
```

Le planificateur de tâches conviendrait aussi, mais son dossier racine demande
une élévation.

**macOS**, un agent de lancement dans
`~/Library/LaunchAgents/com.nico579.blink2video.plist` :

```xml
<plist version="1.0"><dict>
  <key>Label</key><string>com.nico579.blink2video</string>
  <key>ProgramArguments</key>
  <array><string>/path/to/blink2video</string><string>serve</string><string>all</string><string>--loop</string><string>10</string><string>download</string><string>--from</string><string>cloud</string><string>--loop</string><string>1</string></array>
  <key>WorkingDirectory</key><string>/path/to</string>
  <key>RunAtLoad</key><true/>
  <key>KeepAlive</key><true/>
</dict></plist>
```

Chargé par `launchctl load`, arrêté par `launchctl unload`.

**Linux**, un service utilisateur systemd dans
`~/.config/systemd/user/blink2video.service` :

```ini
[Service]
ExecStart=/path/to/blink2video blink2video start
WorkingDirectory=/path/to
Restart=on-failure

[Install]
WantedBy=default.target
```

Activé par `systemctl --user enable --now blink2video`, suivi par
`journalctl --user -u blink2video -f`.

Un seul lanceur à la fois : deux donnent deux surveillances, et chaque
notification en double.

</details>

**Mettre à jour.** La même chose que le bouton de l'interface :

```bash
blink2video update               # installer la dernière version publiée
blink2video update --check       # dire seulement s'il en existe une
```

Depuis un clone git, `update` fait un `git pull` au lieu de télécharger une
archive.

Pour le faire à la main, arrêtez d'abord l'instance : elle tient le port de
l'interface et parle au module de synchronisation.

```bash
blink2video stop                 # arrête l'instance et tous ses verbes
```

Puis remplacez le dossier par la nouvelle archive et relancez : le raccourci du
dossier Démarrage sous Windows, `launchctl load` sous macOS, `systemctl --user
start blink2video` sous Linux. La prochaine ouverture de session s'en charge de
toute façon.

`blink2video autostart status` dit ce qui est installé et si une instance tourne. Dans
un terminal, Ctrl+C suffit : c'est `stop` qui existe pour les instances sans
console, qu'un Ctrl+C ne peut pas atteindre et dont tuer le seul processus
parent laissait les verbes orphelins.

## Construction

```bash
python build.py
```

Produit `dist/blink2video/`, environ 110 Mo dont la plus grande part est ffmpeg.
PyInstaller n'est pas un compilateur croisé et le binaire ffmpeg est propre à
chaque plateforme : chaque système exige sa propre construction. Le workflow de
publication s'en charge sur les runners GitHub.

## Politique de signature de code

L'exécutable Windows est signé via [SignPath Foundation](https://signpath.org/),
gratuit pour les projets open source. Seul le mainteneur
([@nico579](https://github.com/nico579)) a un accès en écriture et contrôle le
workflow de signature, avec authentification à deux facteurs obligatoire sur
ce compte. La signature se déclenche depuis le workflow public de release
([release.yml](.github/workflows/release.yml)) à partir du code source étiqueté
dans ce dépôt : aucun binaire n'est signé en dehors de ce pipeline.

## État du projet et usage responsable

Projet indépendant, éprouvé au quotidien sous Windows 10 sur une installation
réelle : un module, quatre caméras, le direct, l'armement et l'archive. Les
exécutables Linux et macOS sont construits et leur chaîne vidéo vérifiée
automatiquement, mais ils n'ont jamais tourné face à du vrai matériel Blink. Les
retours reproductibles sont bienvenus dans les issues.

Filmez de manière responsable. En France, la CNIL admet qu'on surveille son
propre domicile, mais pas la voie publique, ni l'entrée des habitations
voisines. Cet outil ne fait que conserver ce que vos caméras enregistrent déjà,
mais il rend la question plus concrète en constituant une archive durable là où
l'application mobile ne gardait que quelques jours.

Cette archive est une donnée personnelle : images de votre domicile, horaires de
présence qui s'en déduisent, et un fichier de session qui donne accès à votre
compte Amazon. Tout reste sur votre machine, et le `.gitignore` du dépôt exclut
ces fichiers.

## Licence, auteur et crédits

Distribué sous GNU General Public License v3.0 ; voir [LICENSE](LICENSE). Ce
choix est aussi celui qu'impose la cohérence : le bundle Linux embarque une
compilation GPL de ffmpeg, seule à disposer de libfreetype.

Conçu et architecturé par Nicolas Martin ([@nico579](https://github.com/nico579)).
Code développé avec l'assistance de Claude (Anthropic) comme outil de
développement.

blink2video doit aussi beaucoup aux personnes qui s'en servent et prennent le
temps de dire ce qui pourrait aller mieux. Les idées et les retours de
[@MarkusKress](https://github.com/MarkusKress), qui le fait tourner sans écran
sur un serveur Linux, ont façonné une bonne part de ce qu'il est aujourd'hui :
les photos à la demande et le webhook qui les déclenche, l'avis de chaque
nouveau clip ou photo, l'usage derrière un proxy inverse ou dans un tableau de
bord, l'horodatage incrusté dans la vidéo, l'arrêt automatique du direct et le
regroupement par jour, une interface et une ligne de commande entièrement en
anglais, la mise à jour et le démarrage automatique sous Linux (voir
[les issues ouvertes par @MarkusKress](https://github.com/nico579/blink2video/issues?q=author%3AMarkusKress)).
[Joel Farthing](https://github.com/joelfarthing) a signé la première
contribution de code venue de l'extérieur : les vignettes du direct et les
photos relues dans l'état courant de Blink
([#24](https://github.com/nico579/blink2video/issues/24),
[#25](https://github.com/nico579/blink2video/pull/25)).

[blinkpy](https://github.com/fronzbot/blinkpy) fournit l'accès à l'API Blink, y
compris le protocole `immis` sans lequel le direct serait hors de portée, et
[ffmpeg](https://ffmpeg.org/) fait tout le travail vidéo. Les notes de
[BlinkMonitorProtocol](https://github.com/MattTW/BlinkMonitorProtocol) ont servi
à comprendre ce que l'API offre, et surtout ce qu'elle n'offre pas.

Sans lien avec Blink ni Amazon. Blink est une marque d'Amazon.