Le cache src_*.MP4 sur les workers s empile: 12 fichiers pour 82 GB au pire.
Le thin pool LVM sur le host Proxmox est trop petit (810 GB pour 1144 GB
thick-provisionned) et se remplit a 100% en quelques heures de pipeline
-> I/O errors -> VMs auto-paused -> tout casse.
Fix: delete src_*.MP4 immediatement apres count_frames (les frames sont
deja extraites), puis fstrim en fin de job pour que le thin pool reclaim
les blocks immediatement via DISCARD/UNMAP.
Le setsid bash lance ffmpeg puis ecrit le code de retour:
echo $? > exit_file
Avec test -f on matchait le fichier pendant que le shell le creait vide
(write() du "> exit_file" cree le fichier avant fwrite). Resultat:
code_str="" -> isdigit()=False -> rc=1 -> ffmpeg failed false positive.
Fix: test -s (existe ET non-vide) pour attendre que echo ait termine.
- estimate_vram_mib: 3500+13*frames (absurde 110GB pour 8k frames) ? 6000 MiB fixe
(windowed+offload_to_cpu plafonne la VRAM indépendamment du total frames)
- do_reconstruct: stride adaptatif basé sur RAM worker (23GB .87, 62GB .84)
load_fn.py stack le tensor complet en CPU RAM (~3.15 MB/frame)
budget 55% RAM ? stride 2-3 pour jobs >4k frames
Debloque tous les jobs avant aucun ne pouvait passer pick_worker car
estimate dépassait la VRAM totale des GPUs.
- threading: main loop spawns run_one in a thread per queued job; up to len(WORKERS) concurrent.
- pick_worker: thread-safe VRAM reservation to avoid two threads picking the same GPU.
- pop_queued/pop_queued_stitch: atomic SELECT+UPDATE sous BEGIN IMMEDIATE (status claimed).
- Heartbeat daemon: thread qui ecrit dispatcher.heartbeat toutes les 5s (fini le faux dead pendant les jobs longs).
- run_one: libere la reservation VRAM sur finally (error/done/queued).
- dispatcher.py : ffmpeg lancé en background (setsid), polling du
nombre de frames toutes les 5s → mise à jour du champ `progress`
en DB. ffprobe estime le total avant lancement pour calculer le %.
- _jobs_table.html : barre de progression visible sur les jobs
en status extracting/running
- style.css : styles .prog-wrap/.prog-fill/.prog-text
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ingest.py : --remote-host <alias> pour scanner/exiftool via SSH, stocke
les chemins avec préfixe "alias:" pour que le worker sache puller direct
- dispatcher.py : scp_to_worker détecte "host:path" et fait pull remote
(worker → source host) au lieu du double hop via dispatcher
- _path_basename gère les paths préfixés pour ffmpeg
Permet d'ingester les vidéos depuis n'importe quelle machine accessible
en SSH sans passer 145GB par le conteneur FastAPI.
Le viser de demo.py était tué dès que le PLY était écrit (pour libérer la VRAM),
donc les liens dans le dashboard menaient vers ERR_CONNECTION_REFUSED.
Ajout d'un viewer standalone indépendant :
- scripts/viser_ply.py : charge un PLY via open3d + sert via viser (sans GPU),
subsample random à 2M pts max pour rester fluide
- app/main.py : routes POST /jobs/{id}/view et /stitches/{id}/view qui scp
le script sur le worker et lancent un viser détaché (nohup+setsid+disown via
wrapper shell déposé sur le worker)
- templates : remplace <a href> par <button class=viewer-btn> qui POST puis
window.open de l'URL retournée
- Dockerfile : copie scripts/ dans l'image (nécessaire pour scp-er viser_ply.py)
Quand un seul PLY est disponible (1 segment, 1 caméra), aucun alignement
n'est nécessaire. On copie directement le PLY en output et on marque la
stitch done plutôt qu'error. Cross-AUV est quand même tenté si conditions remplies.
- dispatcher: scp du MP4 source vers le worker avant ffmpeg (les chemins .82 ne sont pas accessibles côté .87)
- dispatcher: wrapper shell autour de demo.py pour killer viser dès que le PLY est écrit (setsid + pkill -f frames_dir)
- dispatcher: PLY_ok fallback — accepte rc!=0 si le PLY existe et a une taille > 0
- dispatcher: fallback frame_count abaissé à 150 pour l'estimation VRAM
- ingest: strip du suffixe timezone (+00:00) des timestamps exiftool QuickTimeUTC=1
Testé bout-en-bout sur GX010001.MP4 (70 frames, 10.6M pts PLY, VRAM peak 9.4 GB, kill viser OK).
- nvidia-smi : +temperature.gpu + power.draw
- UI : tags °C / W / espace disque libre
- Dispatcher heartbeat toutes les 4s → point vert/rouge en haut du monitor
- Fix Docker SSH : copie + chmod 600 au démarrage (Bad owner)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Table stitches (per_auv + cross_auv) avec cancel/retry API
- Dispatcher : PLY export auto (--save_ply), trigger stitch en cascade
quand tous les jobs d'un AUV sont done
- UI : section stitch live depuis DB avec statuts/durées/boutons
- Fix : <base href="/cosma-qc/"> + chemins relatifs pour Caddy subpath
- open3d 0.19.0 installé sur gpu (.87)
- SSH key .82→.87 configurée, alias gpu ajouté sur .82
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>