Files
stripstream-librarian/PLAN_THUMBNAILS.md

4.2 KiB

Plan: Génération des vignettes à l'index

1. Base de données

Migration SQL (0010_add_thumbnails.sql)

  • Ajouter thumbnail_path TEXT à la table books (nullable)
  • Ajouter settings pour thumbnails dans app_settings:
    {
      "thumbnail": {
        "enabled": true,
        "width": 300,
        "height": 400,
        "quality": 80,
        "format": "webp"
      }
    }
    

2. Configuration

crates/core/src/config.rs

  • Ajouter ThumbnailConfig struct
  • Ajouter champs dans IndexerConfig:
    • thumbnail_width: u32 (défaut: 300)
    • thumbnail_height: u32 (défaut: 400)
    • thumbnail_quality: u8 (défaut: 80)
    • thumbnail_dir: String (défaut: /data/thumbnails)
  • Ajouter getter depuis env vars

3. Indexer - Extraction de la 1ère page

Fonction à créer dans crates/parsers/src/lib.rs

  • extract_first_page(path: &Path, format: BookFormat) -> Result<Vec<u8>>
    • Réutiliser logique de pages.rs:extract_cbz_page
    • Réutiliser logique de pages.rs:extract_cbr_page
    • Réutiliser logique de pages.rs:render_pdf_page

Fonction de génération vignette dans apps/indexer/src/main.rs

  • generate_thumbnail(image_bytes: &[u8], config: &ThumbnailConfig) -> Result<Vec<u8>>

    • Load image avec image::load_from_memory
    • Resize avec image::resize (ratio kept)
    • Encode en WebP avec webp::Encoder
  • save_thumbnail(book_id: Uuid, thumbnail_bytes: &[u8], config: &ThumbnailConfig) -> Result<String>

Intégration dans scan_library

  • Après parsing metadata, extraire 1ère page
  • Générer vignette et sauvegarder
  • Stocker chemin en DB (via batch insert)

4. Indexer - WalkDir parallèle

Remplacement de WalkDir séquentiel

  • Utiliser rayon pour paralléliser le scan:
    let total_files: usize = library_paths.par_iter()
        .map(|root_path| { ... })
        .sum();
    
  • Ajouter rayon = "1.10" dans workspace dependencies

5. API - Service des vignettes

Mise à jour models dans apps/api/src/books.rs

  • Ajouter thumbnail_url: Option<String> à BookItem
  • Ajouter thumbnail_url: Option<String> à BookDetails
  • Mise à jour des requêtes SQL pour récupérer thumbnail_path

Nouvelle route dans apps/api/src/main.rs

  • Route /books/:id/thumbnail (GET)
    • Retourne fichier statique depuis thumbnail_path
    • Content-Type: image/webp
    • Cache-Control: public, max-age=31536000

Suppression cache 1ère page (optionnel)

  • Optionnel: simplifier pages.rs car thumbnail pré-générée
  • Garder render pour pages > 1

Adapter backoffice

La recupération des thumbnail est fait par une route page/1.

  • Passer par la nouvelle route avec une route clean /thumbnail pour chaque cover.

refacto code entre api et indexer

En fait l'indexer pourrait appeler l'api pour qu'il fasse les vignettes et c'est l'api qui est responsable des images et des lectures ebooks. Je préfère que chaque domaine soit bien respecté. A la fin d'une build, on appelle l'api pour faire le checkup des thumbnails. Il faudra que coté backoffice on voit partout ou on peut voir le traitement live des jobs, une phase ou on voit en sse le traitement des thumbnails. Coté api, si on a pas de thumbnail on passe par le code actuel de pages.


6. Settings API

Endpoint settings existant

  • Vérifier que /settings expose thumbnail config
  • Ajouter endpoint PUT pour mettre à jour thumbnail settings

7. Taches diverses

  • Ajouter dependency image et webp dans indexer Cargo.toml
  • Build release vérifié

Ordre d'implémentation suggéré

  1. Migration DB + settings
  2. Config + parsers (extract first page)
  3. Indexer thumbnail generation + save to disk
  4. API serve thumbnail
  5. Parallel walkdir
  6. Tests & polish (à faire)

Post-déploiement

  • Appliquer migration SQL: psql -f infra/migrations/0009_add_thumbnails.sql
  • Créer dossier thumbnails: mkdir -p /data/thumbnails
  • Configurer env vars si besoin:
    • THUMBNAIL_ENABLED=true
    • THUMBNAIL_WIDTH=300
    • THUMBNAIL_HEIGHT=400
    • THUMBNAIL_QUALITY=80
    • THUMBNAIL_DIRECTORY=/data/thumbnails