diff --git a/stopmotion.sh b/stopmotion.sh index 0f6e381..e580ce6 100755 --- a/stopmotion.sh +++ b/stopmotion.sh @@ -53,3 +53,60 @@ if [ ! -d "$INPUT" ]; then echo "Erreur : le dossier d'images '$INPUT' n'existe pas." >&2 exit 1 fi + +IMAGES_ABS_DIR=$(cd "$INPUT" && pwd) +IMAGES=$(LC_ALL=C find "$IMAGES_ABS_DIR" -maxdepth 1 -type f \( -iname '*.jpg' -o -iname '*.jpeg' -o -iname '*.png' -o -iname '*.heic' \) | LC_ALL=C sort) +if [ -z "$IMAGES" ]; then + echo "Erreur : aucune image (jpg, jpeg, png, heic) trouvée dans '$INPUT'." >&2 + exit 1 +fi +COUNT=$(printf '%s\n' "$IMAGES" | wc -l | tr -d ' ') + +if [ ! -d "$(dirname "$OUTPUT")" ]; then + echo "Erreur : le dossier de sortie '$(dirname "$OUTPUT")' n'existe pas." >&2 + exit 1 +fi + +if [ -e "$OUTPUT" ] && [ "$ASSUME_YES" -ne 1 ]; then + read -r -p "'$OUTPUT' existe déjà. L'écraser ? [o/N] " reponse + case $reponse in + o|O|y|Y|oui|Oui) ;; + *) echo "Abandon." ; exit 0 ;; + esac +fi + +OUT_DIR=$(cd "$(dirname "$OUTPUT")" && pwd) +OUT_NAME=$(basename "$OUTPUT") +LIST_FILE=$(mktemp "$OUT_DIR/.stopmotion.XXXXXX") +trap 'rm -f "$LIST_FILE"' EXIT + +quote_ffconcat() { + local s=$1 + s=${s//\\/\\\\} + s=${s//\'/\'\\\'\'} + printf "file '%s'\n" "$s" +} + +DURATION=$(awk -v f="$FPS" 'BEGIN{printf "%.6f", 1/f}') +{ + echo "ffconcat version 1.0" + while IFS= read -r img; do + quote_ffconcat "$img" + printf 'duration %s\n' "$DURATION" + done <<< "$IMAGES" +} > "$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" + echo "Erreur : l'encodage ffmpeg a échoué." >&2 + exit 1 +fi + +DURATION_VIDEO=$(awk -v c="$COUNT" -v f="$FPS" 'BEGIN{printf "%.2f", c/f}') +SIZE_HUMAN=$(du -h "$OUT_DIR/$OUT_NAME" | cut -f1 | tr -d ' ') +echo "Vidéo créée : $OUT_NAME ($COUNT images, ${FPS} fps, ${DURATION_VIDEO} s, ${SIZE_HUMAN})"