# Pipeline cosma-qc

## Vue d’ensemble

Le pipeline cosma-qc traite les vidéos GoPro brutes acquises par les drones sous-marins AUV COSMA pour produire des nuages de points 3D denses (PLY) et des exports web (GLB).

## Flux de données global

    z620 (/mnt/portablessd)
    ├── GX*.MP4  (brut)
         │
         ▼  [1. Ingest]
    SQLite DB (jobs)
         │
         ▼  [2. Extraction ffmpeg]
    GPU worker  /cosma-qc-frames/job_{id}/frame_%06d.jpg
         │
         ▼  [3. Reconstruction lingbot-map]
    GPU worker  /cosma-qc-frames/job_{id}/reconstruction.ply
         │
         ▼  [4. Stitch per_auv]
    GPU worker  /cosma-qc-frames/stitch_{N}.ply  (par AUV)
         │
         ▼  [5. Stitch cross_auv]
    GPU worker  /cosma-qc-frames/stitch_global.ply
         │
         ▼  [6. Export GLB  (à la demande)]
    GPU worker  /cosma-qc-frames/job_{id}/reconstruction.glb

## Étape 1 — Ingest

Script : scripts/ingest.py

Rôle : Scanner le SSD de z620, regrouper les MP4 GoPro par AUV/GoPro/segment temporel et écrire les jobs dans la base SQLite.

Logique de regroupement :

- Les fichiers sont groupés par numéro de caméra GoPro (GXXX).

- Un nouveau segment est créé si l’écart entre deux fichiers dépasse 5 minutes.

- Chaque segment → un job en base avec statut pending.

Structure d’un job en base :

    CREATE TABLE jobs (
        id INTEGER PRIMARY KEY,
        auv TEXT,
        gopro TEXT,
        segment INTEGER,
        files TEXT,          -- JSON list of z620:/path/GX*.MP4
        status TEXT,         -- pending / running / done / failed
        worker TEXT,
        created_at TIMESTAMP,
        updated_at TIMESTAMP
    );

Les chemins vidéo sont stockés sous la forme z620:/chemin/absolu/GX*.MP4 pour indiquer que la source est sur z620, pas sur le worker GPU.

## Étape 2 — Extraction des frames

Fonction : do_extract dans le dispatcher (core .82)

Outil : ffmpeg

Paramètres d’extraction :

    ffmpeg -i input.mp4         -vf fps=2,scale=1920:1080         -q:v 2         {frames_dir}/job_{id}/frame_%06d.jpg

Particularité z620 : lorsque la source est z620:/…, ffmpeg s’exécute directement sur z620 via SSH — seuls les JPEG voyagent sur le réseau. Les MP4 bruts ne quittent jamais z620.

Filtre hors-eau (heuristique de luminosité) :

- Les frames dont la luminosité moyenne est au-dessus d’un seuil sont supprimées (ciel, surface, hors-eau).

- Ce filtre réduit le bruit dans la reconstruction.

Reprise sur crash :

- Un fichier marqueur .video_N.done est créé après chaque MP4 traité.

- En cas de redémarrage, les vidéos déjà traitées sont ignorées.

## Étape 3 — Reconstruction 3D

Fonction : do_reconstruct

Outil : lingbot-map (demo.py) sur le worker GPU

Entrée : répertoire de frames {worker_frames_dir}/job_{id}/

Sortie : {worker_frames_dir}/job_{id}/reconstruction.ply (nuage de points dense, jusqu’à 150 millions de points)

Un viewer Viser est automatiquement démarré sur le port 8100 + job_id pendant la reconstruction pour visualisation en temps réel.

    # Visualiser pendant reconstruction
    # naviguer vers http://{worker_ip}:{8100+job_id}

## Étape 4 — Stitch par AUV

Fonction : do_stitch_per_auv

Déclenchement : automatique quand tous les jobs d’un AUV sont en statut done.

Outil : cosma-stitch.py

Opération : alignement et fusion des PLY de tous les segments d’un même AUV.

Sortie : {worker_frames_dir}/stitch_{N}.ply

Ce stitch s’exécute sur le worker qui détient les PLY (pas de copie inter-workers).

## Étape 5 — Stitch cross-AUV

Fonction : do_stitch_cross_auv

Déclenchement : automatique quand tous les stitches per_auv sont validés.

Opération : fusion de tous les PLY par AUV en un nuage de points global final.

Sortie : {worker_frames_dir}/stitch_global.ply

## Étape 6 — Export GLB (à la demande)

Outil : trimesh (conversion PLY → GLB)

Sous-échantillonnage : 5 millions de points (adapté web/navigateur)

Sortie : {worker_frames_dir}/job_{id}/reconstruction.glb

Un serveur HTTP minimal est lancé sur le worker (port 8300) pour le téléchargement :

    # Sur le worker
    python3 -m http.server 8300 --directory {worker_frames_dir}

    # Télécharger depuis un PC
    wget http://{worker_ip}:8300/job_{id}/reconstruction.glb

## Statuts de jobs

Statut | Description
--- | ---
pending | Job créé, en attente de dispatch
running | En cours de traitement (extraction ou reconstruction)
done | Reconstruction terminée, PLY disponible
failed | Erreur — voir logs du dispatcher