Permet de modifier la date de modification des fichiers images selon la date de prise de vue du frame, utile pour le tri par date dans les gestionnaires de fichiers. Utilise os.utime() pour modifier atime et mtime. Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
125 lines
3.5 KiB
Markdown
125 lines
3.5 KiB
Markdown
# CLAUDE.md - Contexte projet pour agent IA
|
|
|
|
## Description du projet
|
|
|
|
Script Python de gestion des métadonnées EXIF pour photos argentiques. Lit un fichier JSON généré par l'application mobile **Exif Notes** et écrit les métadonnées dans les fichiers images correspondants.
|
|
|
|
## Stack technique
|
|
|
|
- **Python 3.11+** (utilise `zoneinfo` natif)
|
|
- **exiftool** (CLI) appelé via `subprocess` — pas de wrapper Python
|
|
- **pytest** pour les tests
|
|
- **flake8** pour le linting (max-line-length=100)
|
|
|
|
## Structure du projet
|
|
|
|
```
|
|
json_to_metadata/
|
|
├── __init__.py # Version du package
|
|
├── cli.py # Point d'entrée CLI (argparse)
|
|
├── json_parser.py # Lecture et validation du JSON
|
|
├── metadata_mapper.py # Mapping JSON → tags EXIF
|
|
├── exif_writer.py # Écriture EXIF via exiftool
|
|
└── xmp_writer.py # Génération de fichiers XMP sidecar
|
|
|
|
tests/
|
|
├── test_json_parser.py
|
|
├── test_metadata_mapper.py
|
|
├── test_exif_writer.py
|
|
└── test_xmp_writer.py
|
|
```
|
|
|
|
## Commandes utiles
|
|
|
|
```bash
|
|
# Activer l'environnement
|
|
source venv/bin/activate
|
|
|
|
# Lancer le script
|
|
python -m json_to_metadata <fichier.json> -d <dossier_images>
|
|
|
|
# Options CLI
|
|
# -v, --verbose Mode verbeux (DEBUG)
|
|
# --dry-run Affiche sans exécuter
|
|
# --force-xmp Force création XMP même pour TIFF/JPEG
|
|
# --set-file-date Modifie le mtime des fichiers selon la date de prise de vue
|
|
|
|
# Tests
|
|
pytest tests/ -v
|
|
|
|
# Linting
|
|
flake8 json_to_metadata/ tests/ --max-line-length=100
|
|
```
|
|
|
|
## Format JSON attendu (Exif Notes)
|
|
|
|
```json
|
|
{
|
|
"id": "roll-001",
|
|
"camera": { "make": "Nikon", "model": "FM2" },
|
|
"lens": { "make": "Nikon", "model": "Nikkor 50mm f/1.4" },
|
|
"filmStock": { "make": "Kodak", "model": "Portra 400" },
|
|
"iso": 400,
|
|
"frames": [
|
|
{
|
|
"id": 1,
|
|
"date": "2024-03-15T14:30",
|
|
"shutter": "1/125",
|
|
"aperture": "f/2.8",
|
|
"focalLength": 50,
|
|
"location": { "latitude": 48.8584, "longitude": 2.2945 },
|
|
"note": "Description de la photo",
|
|
"flashUsed": false,
|
|
"lightSource": "daylight"
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
## Mapping JSON → EXIF
|
|
|
|
| Champ JSON | Tag EXIF |
|
|
|------------|----------|
|
|
| `camera.make/model` | `Make`, `Model` |
|
|
| `lens.make/model` | `LensMake`, `LensModel` |
|
|
| `iso` | `ISO` |
|
|
| `frame.date` | `DateTimeOriginal`, `CreateDate` |
|
|
| `frame.shutter` | `ExposureTime`, `ShutterSpeedValue` |
|
|
| `frame.aperture` | `FNumber`, `ApertureValue` |
|
|
| `frame.focalLength` | `FocalLength` |
|
|
| `frame.location.*` | `GPSLatitude/Ref`, `GPSLongitude/Ref` |
|
|
| `frame.note` | `ImageDescription`, `UserComment` |
|
|
| `frame.flashUsed` | `Flash` |
|
|
| `filmStock.*` | Inclus dans `ImageDescription` |
|
|
|
|
## Formats supportés
|
|
|
|
### Vitesses d'obturation
|
|
- Fractions : `1/125`, `1/1000`
|
|
- Secondes : `2`, `2s`, `2"`, `4'`
|
|
- Mode Bulb : `B`, `bulb`
|
|
|
|
### Dates
|
|
- ISO complet : `2024-03-15T14:30:00`
|
|
- Sans secondes : `2024-03-15T14:30`
|
|
- Avec timezone : `2024-03-15T14:30:00+02:00`
|
|
- Date seule : `2024-03-15`
|
|
|
|
### Images
|
|
- EXIF intégré : `.tif`, `.tiff`, `.jpg`, `.jpeg`
|
|
- Support partiel (fallback XMP) : `.avif`, `.heic`, `.webp`
|
|
- XMP sidecar uniquement : autres formats
|
|
|
|
## Conventions de code
|
|
|
|
- Docstrings en français
|
|
- Messages de log en français
|
|
- Fuseau horaire par défaut : `Europe/Paris`
|
|
- Pas d'emoji sauf demande explicite
|
|
|
|
## Points d'extension possibles
|
|
|
|
- Ajout de nouveaux tags EXIF dans `metadata_mapper.py` (fonction `map_frame_to_exif`)
|
|
- Nouveaux formats de date dans `parse_date()` (liste `formats`)
|
|
- Support de nouveaux formats d'image dans `exif_writer.py` (constantes `*_EXTENSIONS`)
|