Refonte : templates, balades, photos web, aperçus, carte globale
- Mise en page sortie du Python : Scripts/templates/ (Jinja2 + CSS/JS communs copiés dans assets/ de chaque voyage) - Voyages rangés dans un sous-dossier (Balades/…) : rubriques sur l'accueil, 2 plus récents par rubrique, pages voyages.html et balades.html - prepare_web.py : photos allégées (photos_web/) et images d'aperçu des vidéos (apercus/) - Voyage d'une seule journée : la page du voyage est la carte du jour - Carte globale de l'accueil (OpenStreetMap) : voyages du site + cartes Google My Maps récupérées (mymaps.txt, _mymaps/), moto par voyage (moto.txt) - KML par voyage pour My Maps - compress.sh : réencode une sortie illisible (encodage interrompu) ; repli automatique sur l'autre qualité dans la page - Corrections : CSV vide (voyage sans photo), racine de genere_site.sh, fichiers ._ de macOS - README réécrit, commentaires allégés Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Mf2kATMtqVABHSYdxJMnim
This commit is contained in:
1 parent
5a04f159ca
commit
97b936fd3e
17 files changed
+2042
-829
No files matched your search
+27
-45
@@ -1,20 +1,18 @@
|
||||
#!/bin/bash
|
||||
# =============================================================================
|
||||
# EXTRACTION DES MÉTADONNÉES — photos EXIF + traces GPS embarquées GoPro
|
||||
# EXTRACTION DES POSITIONS GPS — photos (EXIF) et rushs GoPro (GPS embarqué)
|
||||
#
|
||||
# Produit deux CSV sans en-tête, consommés par genere_carte.py :
|
||||
# Produit deux CSV sans en-tête, lus par genere_carte.py :
|
||||
# export_photos.csv : fichier, date, lat, lon, alt
|
||||
# export_videos.csv : fichier, date GPS, lat, lon, alt, vitesse
|
||||
#
|
||||
# Usage : ./extraction_infos.sh [dossier_voyage]
|
||||
#
|
||||
# Variables :
|
||||
# VIDEO_GPS=first (défaut) un seul point GPS par rush — RAPIDE.
|
||||
# C'est tout ce que genere_carte.py utilise pour poser
|
||||
# le marqueur : `folium.Marker(location=pts_v[0])`.
|
||||
# VIDEO_GPS=full déroule toute la trace GPS de chaque rush.
|
||||
# Lit l'intégralité de chaque fichier : compter plusieurs
|
||||
# minutes par rush sur un disque externe.
|
||||
# VIDEO_GPS=first (défaut) premier point GPS de chaque rush, c'est là que
|
||||
# genere_carte.py pose le marqueur. Rapide.
|
||||
# VIDEO_GPS=full toute la trace de chaque rush. Lit les fichiers en entier :
|
||||
# plusieurs minutes par rush sur un disque externe.
|
||||
# VARIANTE=D|A|B|C force le mode d'extraction vidéo (voir plus bas)
|
||||
# =============================================================================
|
||||
|
||||
@@ -48,31 +46,27 @@ nlines() { awk 'END{print NR+0}' "$1" 2>/dev/null || echo 0; }
|
||||
# =============================================================================
|
||||
# FORMATS
|
||||
#
|
||||
# `exiftool -p` supprime la LIGNE ENTIÈRE dès qu'UN SEUL tag du format est
|
||||
# absent. Sur un rush GoPro, [Main] porte GPSLatitude/GPSLongitude mais PAS
|
||||
# GPSDateTime, alors que [Doc1] porte tout. Un format à six tags peut donc ne
|
||||
# rien produire sur un fichier parfaitement géolocalisé.
|
||||
# `exiftool -p` supprime toute la ligne dès qu'un seul tag du format manque.
|
||||
# Sur un rush GoPro, le document principal porte la position mais pas
|
||||
# GPSDateTime (qui est dans [Doc1]) : un format qui réclame la date ne
|
||||
# produit alors rien. Ne PAS ajouter -f pour forcer : avec -ee, -f fait perdre
|
||||
# l'itération par document et ne sort plus qu'une ligne vide.
|
||||
#
|
||||
# ⚠️ NE JAMAIS ajouter -f pour « forcer » l'affichage. Vérifié en test :
|
||||
# `-ee -p '$FileName,$SampleRate'` sur un fichier multi-documents donne
|
||||
# 0 ligne sans -f, mais UNE SEULE ligne « fichier,- » AVEC -f — l'option fait
|
||||
# perdre à -ee son itération par document. C'est pire que le mal.
|
||||
#
|
||||
# La parade : trois modes, essayés sur les premiers rushs ; on garde celui
|
||||
# qui produit quelque chose.
|
||||
# D'où quatre modes, essayés sur les premiers rushs ; on garde le premier qui
|
||||
# produit quelque chose :
|
||||
# D = lecture des tags un par un, analysée par awk (atteint [Doc1])
|
||||
# A = format complet (date, lat, lon, alt, vitesse)
|
||||
# B = format réduit (date, lat, lon) — tolère l'absence d'alt/vitesse
|
||||
# C = format réduit + -ee3, qui détaille davantage les sous-documents
|
||||
# B = format réduit (date, lat, lon)
|
||||
# C = format réduit + -ee3 (sous-documents détaillés)
|
||||
# =============================================================================
|
||||
FMT_PHOTOS='"$FileName",$DateTimeOriginal,$GPSLatitude,$GPSLongitude,$GPSAltitude'
|
||||
FMT_PHOTOS_MIN='"$FileName",$DateTimeOriginal,$GPSLatitude,$GPSLongitude'
|
||||
FMT_V_COMPLET='"$FileName",$GPSDateTime,$GPSLatitude,$GPSLongitude,$GPSAltitude,$GPSSpeed'
|
||||
FMT_V_MINIMAL='"$FileName",$GPSDateTime,$GPSLatitude,$GPSLongitude'
|
||||
|
||||
# Reconstruit des lignes CSV depuis la sortie « Tag : valeur » d'exiftool
|
||||
# (noms longs ou courts, avec ou sans préfixe de groupe [Doc1]).
|
||||
PARSE_GPS='
|
||||
# Reconstruit des lignes CSV depuis la sortie « Tag : valeur » de exiftool.
|
||||
# Robuste au format long ("GPS Date Time") comme court ("GPSDateTime"), et au
|
||||
# prefixe de groupe [Main] / [Doc1].
|
||||
{
|
||||
ligne = $0
|
||||
sub(/^\[[^]]*\][ \t]*/, "", ligne)
|
||||
@@ -94,6 +88,8 @@ PARSE_GPS='
|
||||
else if (tag == "GPSAltitude") { if (mode == "full" && n > 0) palt[n] = val }
|
||||
else if (tag == "GPSSpeed") { if (mode == "full" && n > 0) pspd[n] = val }
|
||||
|
||||
# Mode rapide : on sort dès qu on a une date et une position ; exiftool
|
||||
# reçoit alors SIGPIPE et arrête de lire le fichier.
|
||||
if (mode != "full" && flat != "" && dt != "") {
|
||||
print f "," dt "," flat "," flon ",,"; emis = 1; exit
|
||||
}
|
||||
@@ -107,14 +103,6 @@ END {
|
||||
'
|
||||
|
||||
# extrait_video <mode> <fichier> -> lignes CSV sur stdout
|
||||
#
|
||||
# Mode D (par defaut) : on demande les tags un par un et on parse la sortie
|
||||
# « Tag : valeur ». C est la seule methode qui atteint reellement [Doc1] :
|
||||
# `-p` ne voit que [Main], lequel porte la position mais PAS GPSDateTime, si
|
||||
# bien qu un format reclamant la date ne produit jamais rien. Verifie sur une
|
||||
# sortie exiftool reelle de GoPro Hero 9 (GX011569.MP4).
|
||||
# En mode rapide, awk sort des qu il a une date et une position : exiftool
|
||||
# recoit SIGPIPE et cesse de lire le fichier.
|
||||
extrait_video() {
|
||||
local m="$1" f="$2" nom
|
||||
nom=$(basename "$f")
|
||||
@@ -133,17 +121,15 @@ extrait_video() {
|
||||
: > "$CSV_PHOTOS"
|
||||
if [ -d "$PHOTOS_DIR" ]; then
|
||||
echo "📸 Photos : analyse en cours…"
|
||||
# UN SEUL appel exiftool pour tout le dossier : chaque lancement du binaire
|
||||
# coûte 150-250 ms (Perl). Mesuré sur 150 photos : 29,3 s → 0,97 s.
|
||||
# Un seul appel exiftool pour tout le dossier : chaque lancement coûte
|
||||
# ~200 ms (Perl). Seconde passe au format réduit pour rattraper les photos
|
||||
# sans altitude, écartées par la première.
|
||||
exiftool -n -q -ext jpg -ext jpeg -p "$FMT_PHOTOS" "$PHOTOS_DIR" \
|
||||
2>>"$ERRLOG" > "$TMPD/p1.csv"
|
||||
|
||||
# Seconde passe, format réduit : rattrape les photos écartées par la
|
||||
# première faute d'altitude. Deux appels batch restent sous la seconde.
|
||||
exiftool -n -q -ext jpg -ext jpeg -p "$FMT_PHOTOS_MIN" "$PHOTOS_DIR" \
|
||||
2>>"$ERRLOG" | awk '{print $0 ","}' > "$TMPD/p2.csv"
|
||||
|
||||
# Fusion : tout p1, plus les fichiers de p2 absents de p1.
|
||||
# Fusion : tout p1, plus les photos de p2 absentes de p1.
|
||||
cat "$TMPD/p1.csv" > "$CSV_PHOTOS"
|
||||
awk -F, 'NR==FNR {vu[$1]=1; next} !($1 in vu)' "$TMPD/p1.csv" "$TMPD/p2.csv" >> "$CSV_PHOTOS"
|
||||
|
||||
@@ -163,8 +149,7 @@ else
|
||||
rushs=()
|
||||
for f in "$RUSHS_DIR"/*.mp4 "$RUSHS_DIR"/*.mov; do
|
||||
[ -e "$f" ] || continue
|
||||
# macOS depose un fichier AppleDouble « ._nom » a cote de chaque
|
||||
# fichier sur les disques non-HFS (exFAT). Ce ne sont pas des videos.
|
||||
# « ._nom » : métadonnées que macOS dépose sur les disques non-HFS (exFAT).
|
||||
case "$(basename "$f")" in ._*) continue ;; esac
|
||||
rushs+=("$f")
|
||||
done
|
||||
@@ -181,9 +166,7 @@ else
|
||||
echo " (VIDEO_GPS=full pour dérouler la trace entière)"
|
||||
fi
|
||||
|
||||
# --- Choix du mode d'extraction ---
|
||||
# Testé sur 3 rushs au maximum : inutile de parcourir 552 fichiers
|
||||
# pour découvrir qu'un mode ne marche pas.
|
||||
# Choix du mode, testé sur 3 rushs au plus.
|
||||
if [ -z "$VARIANTE" ]; then
|
||||
echo " 🔎 recherche du mode d'extraction…"
|
||||
for essai in D A B C; do
|
||||
@@ -218,8 +201,7 @@ else
|
||||
if [ "$VIDEO_GPS" = "full" ]; then
|
||||
extrait_video "$VARIANTE" "$f" >> "$CSV_VIDEOS"
|
||||
else
|
||||
# `head -n 1` ferme le tuyau : exiftool reçoit SIGPIPE et
|
||||
# s'arrête sans lire la fin du fichier.
|
||||
# head ferme le tuyau : exiftool s'arrête sans lire la fin du fichier.
|
||||
extrait_video "$VARIANTE" "$f" | head -n 1 >> "$CSV_VIDEOS"
|
||||
fi
|
||||
|
||||
|
||||
Reference in new issue
Block a user