diff --git a/docs/superpowers/specs/2026-08-31-stopmotion-script-design.md b/docs/superpowers/specs/2026-08-31-stopmotion-script-design.md new file mode 100644 index 0000000..8f4fea6 --- /dev/null +++ b/docs/superpowers/specs/2026-08-31-stopmotion-script-design.md @@ -0,0 +1,52 @@ +# Design — Script réutilisable de stop motion + +Date : 2026-08-31 +Statut : validé par l'utilisateur + +## Contexte + +Le projet contient un dossier `images/` (42 photos HEIC 3056x3056, prises par iPhone, triées par nom = ordre chronologique) et une vidéo `stop_motion.mp4` générée manuellement avec ffmpeg (12 fps, 1080x1080, 3,5 s). Le build ffmpeg installé (8.1.2, Homebrew) décode le HEIC mais ne supporte pas `-pattern_type glob` ; la génération manuelle a utilisé le concat demuxer avec un fichier `ffconcat`. + +Objectif : un script réutilisable pour regénérer la vidéo depuis n'importe quel dossier d'images, sans dépendance au-delà de ffmpeg. + +## Décisions + +- **Approche choisie** : script bash unique (`stopmotion.sh`) à la racine. Les alternatives (Python/argparse, Makefile) ont été écartées : bash suffit, ffmpeg fait tout le travail, aucune dépendance supplémentaire. +- **Usage visé** : flexible — détection automatique des formats d'images, options CLI simples. + +## Interface + +``` +./stopmotion.sh # ./images → ./stop_motion.mp4, 12 fps, 1080px +./stopmotion.sh -i photos -o film.mp4 -f 15 -s 720 -y +``` + +| Option | Défaut | Rôle | +|--------|--------|------| +| `-i` | `./images` | dossier d'images | +| `-o` | `./stop_motion.mp4` | fichier de sortie | +| `-f` | `12` | fps (cadence stop motion) | +| `-s` | `1080` | taille max du côté long, ratio préservé | +| `-y` | off | écraser la sortie sans demander | +| `-h` | — | aide | + +## Comportement + +1. Vérifie la présence de `ffmpeg` dans le PATH ; sinon message clair + exit 1. +2. Liste les images du dossier d'entrée (extensions `jpg`, `jpeg`, `png`, `heic`, insensible à la casse, premier niveau uniquement), triées par nom (`LC_ALL=C sort`). +3. Erreur explicite si le dossier n'existe pas ou ne contient aucune image (exit 1). +4. Génère un fichier `ffconcat` temporaire (mktemp + trap de nettoyage) : en-tête `ffconcat version 1.0`, puis pour chaque image `file ` + `duration 1/fps` ; dernière image répétée sans durée (contrainte du concat demuxer qui sinon ignore la dernière frame). Les chemins contenant des apostrophes sont échappés (`'` → `'\''`). +5. Encode avec ffmpeg : `-f concat -safe 0`, `libx264`, `yuv420p`, `-movflags +faststart`, filtre `scale=S:S:force_original_aspect_ratio=decrease:force_divisible_by=2`. +6. Affiche un récapitulatif : nombre d'images, fps, durée de la vidéo, taille du fichier de sortie. + +## Gestion des erreurs + +- Options inconnues ou valeur manquante → usage + exit 1. +- Dossier d'entrée inexistant ou sans image → message en français + exit 1. +- Échec d'encodage ffmpeg → le fichier de sortie est supprimé s'il est partiel, exit 1. +- Sortie existante sans `-y` → demande confirmation (refus = exit 0 sans rien faire). +- Codes de sortie non nuls pour toute erreur. + +## Validation + +Rejouer le scénario de référence : `./stopmotion.sh` sans option sur ce projet doit produire une vidéo équivalente à l'actuelle `stop_motion.mp4` (42 frames, 12 fps, 1080x1080, ~3,5 s). Vérifier aussi : `-h`, dossier inexistant, dossier sans image, sortie refusée sans `-y`.