docs: arbitrage e4 (sans répétition, -r FPS) dans spec et plan

This commit is contained in:
herel committed 2026-08-31 21:14:27 +02:00
1 parent 8c6d053aaf
commit 51cb34a163
2 files changed
+5 -6

No files matched your search

@@ -4,7 +4,7 @@
**Goal :** un script bash `stopmotion.sh` qui génère une vidéo stop motion MP4 (H.264) à partir d'un dossier d'images (jpg/jpeg/png/heic), avec options CLI.
**Architecture :** un seul fichier `stopmotion.sh` à la racine. Découverte des images via `find` trié → fichier `ffconcat` temporaire (une entrée `duration` par image, dernière image répétée — contournement du concat demuxer qui ignore sinon la dernière frame) → encodage ffmpeg (libx264, yuv420p, +faststart). Le fichier ffconcat est créé dans le dossier du fichier de sortie (les chemins d'images y sont absolus, le concat demuxer résout les chemins relativement à l'emplacement de la liste).
**Architecture :** un seul fichier `stopmotion.sh` à la racine. Découverte des images via `find` trié → fichier `ffconcat` temporaire (une entrée `duration` par image) → encodage ffmpeg (libx264, yuv420p, +faststart, `-r FPS` en sortie pour une cadence CFR qui garantit la durée complète de la dernière frame). Le fichier ffconcat est créé dans le dossier du fichier de sortie (les chemins d'images y sont absolus, le concat demuxer résout les chemins relativement à l'emplacement de la liste). (Amendement 2026-08-31, arbitrage utilisateur : la répétition de la dernière image prévue initialement créait une 43e frame dupliquée avec la timebase 1/25 des HEIC — variante e4 validée par framehash.)
**Tech Stack :** bash 3.2 (bash système de macOS — pas de tableaux associatifs, pas de `${var,,}`), ffmpeg 8.x (Homebrew, décode le HEIC), `find` BSD.
@@ -16,7 +16,7 @@
- Aucun commentaire dans le code.
- Compatible bash 3.2 (macOS) : pas de fonctionnalités bash 4+.
- Fonctionnement vérifié avec le build ffmpeg 8.1.2 Homebrew (`-pattern_type glob` non supporté → concat demuxer obligatoire).
- Encodage : `-c:v libx264 -pix_fmt yuv420p -movflags +faststart`, filtre `scale=S:S:force_original_aspect_ratio=decrease:force_divisible_by=2`.
- Encodage : `-c:v libx264 -pix_fmt yuv420p -movflags +faststart`, `-r "$FPS"` en sortie, filtre `scale=S:S:force_original_aspect_ratio=decrease:force_divisible_by=2`.
- Validation stricte avant tout traitement : `-f` et `-s` numériques strictement positifs.
- Scénario de référence (validation finale) : `./images` (42 HEIC 3056x3056) sans option → 42 frames, 12 fps, 1080x1080, ~3,5 s.
@@ -210,13 +210,12 @@ DURATION=$(awk -v f="$FPS" 'BEGIN{printf "%.6f", 1/f}')
quote_ffconcat "$img"
printf 'duration %s\n' "$DURATION"
done <<< "$IMAGES"
last=$(printf '%s\n' "$IMAGES" | tail -n 1)
quote_ffconcat "$last"
} > "$LIST_FILE"
if ! ffmpeg -y -hide_banner -loglevel error -stats \
-f concat -safe 0 -i "$LIST_FILE" \
-vf "scale=${SIZE}:${SIZE}:force_original_aspect_ratio=decrease:force_divisible_by=2" \
-r "$FPS" \
-c:v libx264 -pix_fmt yuv420p -movflags +faststart \
"$OUT_DIR/$OUT_NAME"; then
rm -f "$OUT_DIR/$OUT_NAME"
@@ -35,8 +35,8 @@ Objectif : un script réutilisable pour regénérer la vidéo depuis n'importe q
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` ; 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`.
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.
## Gestion des erreurs