Files
stop-motion/docs/superpowers/specs/2026-08-31-stopmotion-script-design.md
T

3.6 KiB

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 <chemin> + duration 1/fps. Les chemins contenant des apostrophes sont échappés (' → '\''). (Amendement du 2026-08-31, arbitrage utilisateur : la « dernière image répétée » prévue initialement créait une 43e frame dupliquée sur ce build ffmpeg — timebase 1/25 des HEIC ; la cadence finale est garantie par -r FPS en sortie, qui couvre aussi la dernière frame.)
  5. Encode avec ffmpeg : -f concat -safe 0, libx264, yuv420p, -movflags +faststart, -r FPS, 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.

Pour des fps élevés (ex. -f 30), le mapping CFR peut dupliquer une image (arrondi au créneau le plus proche face à la timebase 1/25 des HEIC) sans jamais en perdre ; les valeurs -f 12/15/20/24 ont été vérifiées exactes sur le corpus de référence.

Gestion des erreurs

  • Options inconnues ou valeur manquante → usage + exit 1.
  • Valeurs non numériques ou non strictement positives pour -f et -s → erreur + exit 1 (avant tout traitement).
  • 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.