Bibliothèque personnelle de fichiers d'impression 3D : dépose un fichier
(.zip Thingiverse/Printables, .stl, .3mf) dans ~/3D, il est
automatiquement extrait, analysé (dimensions, volume, poids, temps
d'impression estimé), tagué, miniaturé et rangé dans ~/3D_Library/.
Une interface web permet de parcourir/rechercher la bibliothèque et
d'envoyer un modèle vers OrcaSlicer.
Voir docs/SPECS.md pour la spec d'origine du projet.
Deux façons de le lancer :
- Docker (§ Démarrage rapide) — essayer en une commande, sans rien installer.
- systemd (natif Linux) (§ 1 à § 8) — déploiement sans process résident : watcher inotify + interface activée par socket, arrêt auto après inactivité.
~/3D (dépôt unique, surveillé)
│ systemd --user path/timer unit (zéro process au repos)
▼
scanner.py → ~/3D_Library/ (models/, _originals/, library.db)
│
▼
webapp.py (FastAPI, activation par socket)
│
▼
http://library3d.localhost:8765
Aucun process ne tourne en permanence : le watcher (scanner.py) est
déclenché par un systemd --user path unit (inotify, avec un .timer de
secours toutes les 5 min), et l'interface web n'est démarrée qu'à la
première connexion (systemd --user socket unit), puis s'arrête seule
après 10 minutes d'inactivité.
Le plus simple pour essayer, sans rien installer sur l'hôte :
cp .env.example .env # optionnel (port, rétention corbeille)
docker compose up --build -dPuis ouvre http://localhost:8000.
-
Dépose tes fichiers
.stl/.3mf/.zipdans./data/incoming/. -
La bibliothèque persistée (
models/,_originals/,library.db) vit dans./data/library/(volumes bind, versionnés nulle part — cf..gitignore). -
Le catalogage initial se fait au démarrage du conteneur. Pour recataloguer après avoir ajouté des fichiers :
docker compose exec app python3 scanner.py --source /data/incoming --library /data/library
Miniatures 3D : la génération des previews repose sur
f3d(rendu headless), non inclus dans l'image pour la garder légère. Sans lui, les modèles sont catalogués normalement, simplement sans vignette. Pour le déploiement natif systemd ci-dessous,f3dest installé sur l'hôte.
Pour un déploiement Linux natif sans Docker (watcher inotify + activation par socket), suivre les sections ci-dessous.
sudo apt install f3d xvfb # génération des miniatures (F3D, rendu headless)OrcaSlicer doit être installé séparément si tu veux utiliser le bouton
« Ouvrir dans OrcaSlicer » (Flatpak, AppImage, ou paquet — voir la variable
ORCASLICER_CMD plus bas).
Ce projet n'utilise pas de venv (installation globale avec
--break-system-packages sur Debian/Ubuntu récent, PEP 668) :
pip install --user --break-system-packages -r requirements.txtnetworkx et lxml sont requis par trimesh pour charger les .3mf (pas
seulement les .stl) — sans eux, les .3mf sont catalogués avec des
champs d'analyse vides (dimensions/volume/poids à null), sans erreur
visible.
Avant d'activer le watcher automatique, importe une première fois ce qui
traîne déjà dans ~/3D :
mkdir -p ~/3D ~/3D_Library
python3 scanner.py --source ~/3D --library ~/3D_Library~/3D doit être réservé aux fichiers à cataloguer — pas de projets CAD en
cours (FreeCAD, etc.), qui ont vocation à vivre ailleurs (~/Documents/FreeCAD
par exemple) et à n'être copiés dans ~/3D qu'une fois leur export final
prêt à imprimer.
Tout se fait en utilisateur (systemd --user), sans sudo. Les fichiers
unités vivent dans systemd/ et sont symlinkés dans
~/.config/systemd/user/ pour rester versionnés et à jour avec le repo.
mkdir -p ~/.config/systemd/user
# Watcher : scan automatique de ~/3D
ln -sf ~/Documents/Code/3d/library/systemd/3d-library-watch.path ~/.config/systemd/user/
ln -sf ~/Documents/Code/3d/library/systemd/3d-library-watch.service ~/.config/systemd/user/
ln -sf ~/Documents/Code/3d/library/systemd/3d-library-watch.timer ~/.config/systemd/user/
# Interface web : démarrage à la demande, arrêt après inactivité
ln -sf ~/Documents/Code/3d/library/systemd/3d-library-web.socket ~/.config/systemd/user/
ln -sf ~/Documents/Code/3d/library/systemd/3d-library-web.service ~/.config/systemd/user/
# Corbeille : purge définitive quotidienne des modèles supprimés depuis
# plus de TRASH_RETENTION_DAYS jours (30 par défaut)
ln -sf ~/Documents/Code/3d/library/systemd/3d-library-purge.service ~/.config/systemd/user/
ln -sf ~/Documents/Code/3d/library/systemd/3d-library-purge.timer ~/.config/systemd/user/
systemctl --user daemon-reload
systemctl --user enable --now 3d-library-watch.path
systemctl --user enable --now 3d-library-watch.timer
systemctl --user enable --now 3d-library-web.socket
systemctl --user enable --now 3d-library-purge.timer
# Pour que les services tournent même sans session graphique ouverte
# (et survivent à une déconnexion) :
loginctl enable-linger "$USER"Adapte les chemins ci-dessus si le repo n'est pas dans
~/Documents/Code/3d/library (les fichiers .service utilisent %h pour
le $HOME, mais les symlinks doivent pointer vers le bon chemin absolu).
systemctl --user status 3d-library-watch.path # doit afficher "active (waiting)"
systemctl --user status 3d-library-watch.timer # doit afficher "active (running)"
systemctl --user status 3d-library-web.socket # doit afficher "active (listening)"
# Aucun process résident entre deux déclenchements/connexions :
pgrep -af "watch_trigger.py|webapp.py" # ne doit rien afficher au reposjournalctl --user -u 3d-library-watch.service -f # suit un scan en direct
journalctl --user -u 3d-library-web.service -f # suit l'interface web-
Cataloguer un modèle : dépose un
.zip/.stl/.3mfdans~/3D. Rien d'autre à faire — le watcher s'en occupe (jusqu'à ~12s de délai pour laisser le temps à une copie/téléchargement de se terminer). -
Parcourir la bibliothèque : ouvre
http://library3d.localhost:8765(nom défini dans/etc/hosts, voir ci-dessous). Démarre tout seul à la première visite (quelques centaines de ms), s'arrête tout seul après 10 min d'inactivité. -
Lancer manuellement (sans passer par systemd, ex. pour du développement) :
LIBRARY_DB_PATH=~/3D_Library/library.db python3 webapp.py --library ~/3D_Library --port 8765
-
Nom local (une seule fois,
sudo) : ajouter une ligne dans/etc/hosts:echo "127.0.0.1 library3d.localhost" | sudo tee -a /etc/hosts
Vérifier :
getent hosts library3d.localhostdoit renvoyer127.0.0.1.
L'interface servie par webapp.py est une app React/TypeScript buildée avec
Vite (frontend/), chargée depuis frontend/dist/ — pas de serveur Node en
production.
Développement (hot reload, proxy vers le backend FastAPI) :
cd frontend
npm install
npm run dev # serveur de dev Vite sur http://localhost:5173, proxy /api vers http://127.0.0.1:8765Lance le backend en parallèle (LIBRARY_DB_PATH=~/3D_Library/library.db python3 webapp.py --port 8765)
pour que le proxy ait quelque chose à relayer.
Production (ce que sert réellement webapp.py) :
cd frontend
npm run build # génère frontend/dist, servi par FastAPI à la racinefrontend/node_modules et frontend/dist sont ignorés par git — à builder
une fois après chaque clone/déploiement.
| Variable | Défaut | Usage |
|---|---|---|
LIBRARY_DB_PATH |
library.db (dossier courant) |
Chemin vers library.db, lu par webapp.py |
IDLE_TIMEOUT_SECONDS |
600 (10 min) |
Délai d'inactivité avant l'arrêt auto de webapp.py (actif uniquement sous activation par socket) |
ORCASLICER_CMD |
flatpak run com.orcaslicer.OrcaSlicer |
Commande pour ouvrir un modèle dans OrcaSlicer (Linux) |
TRASH_RETENTION_DAYS |
30 |
Nombre de jours avant purge définitive d'un modèle mis à la corbeille (lu par webapp.py et purge_trash.py) |
python3 -m pytest -v84 tests, aucune dépendance système requise au-delà de requirements.txt
(les tests mockent analyze_stl/f3d sauf un test d'intégration réel sur
un .3mf minimal généré à la volée).
systemctl --user disable --now 3d-library-watch.path 3d-library-watch.timer 3d-library-web.socket 3d-library-purge.timer
rm ~/.config/systemd/user/3d-library-watch.{path,service,timer} ~/.config/systemd/user/3d-library-web.{socket,service} ~/.config/systemd/user/3d-library-purge.{service,timer}
systemctl --user daemon-reloadLes données (~/3D_Library/) et les originaux archivés
(~/3D_Library/_originals/) ne sont jamais supprimés par cette opération.