Aller au contenu principal
Mathyou ANDRE
Python (bibliothèque standard)SQLitePyMuPDFgTTS (Google Traduction)HTML / CSS / JavaScriptProxmox (LXC)Tailscale Funnel

Lecteur PDF à voix haute

Application web auto-hébergée qui lit des livres PDF à voix haute, phrase par phrase : bibliothèque personnelle, reprise de lecture, comptes validés par l'admin et statistiques d'écoute.

Code source

Bibliothèque du lecteur : carte « Reprendre la lecture » et grille de couvertures colorées avec leur progression

Un lecteur de PDF à voix haute, hébergé chez moi : on importe ses livres, on clique sur une phrase, et la voix de Google Traduction lit la suite pendant que chaque phrase est surlignée. La lecture reprend là où on s’était arrêté, sur n’importe quel appareil.

L’accès est fermé : chacun peut demander un compte, mais il ne sert à rien tant que je ne l’ai pas validé.

Architecture

Un seul processus Python, sans framework : il sert l’interface, expose une API JSON et appelle la synthèse vocale. Il tourne dans un conteneur LXC sur mon Proxmox et sort sur Internet par Tailscale Funnel, sans ouvrir de port sur la box.

Architecture : le navigateur passe par Tailscale Funnel en HTTPS pour joindre le conteneur LXC Debian sur Proxmox, où serveur.py gère l'API, les comptes et l'extraction des PDF avec une base SQLite ; chaque phrase est synthétisée par Google Traduction via gTTS Architecture : le navigateur passe par Tailscale Funnel en HTTPS pour joindre le conteneur LXC Debian sur Proxmox, où serveur.py gère l'API, les comptes et l'extraction des PDF avec une base SQLite ; chaque phrase est synthétisée par Google Traduction via gTTS

Lecture

Page de lecture : le texte du Comte de Monte-Cristo, la phrase en cours surlignée, le bouton Lire et la vitesse 1,5× en haut
  • La phrase lue est surlignée et suivie à l’écran ; un clic sur n’importe quelle phrase relance la lecture à partir de là
  • Vitesse de 0,8× à 5×, sans changer la hauteur de la voix (le navigateur s’en charge)
  • Les deux phrases suivantes sont synthétisées à l’avance pour éviter les blancs
  • La phrase atteinte et la vitesse sont sauvegardées à chaque phrase

À l’import, le texte du PDF est extrait avec PyMuPDF puis nettoyé : les paragraphes sont reconstitués à partir des retraits et des fins de ligne, les mots coupés en fin de ligne sont recollés, les numéros de page supprimés et les ligatures (fi, ffi) remplacées par les lettres correspondantes.

Bibliothèque

Chaque compte a ses propres livres. La couverture est générée à partir du titre, avec toujours la même couleur pour un même livre, et affiche une barre de progression. L’import se fait par glisser-déposer n’importe où sur la page.

Statistiques

Page de statistiques : temps d'écoute total, tuiles chiffrées, graphique des minutes d'écoute par jour sur 30 jours, livres les plus écoutés et tableau de tous les utilisateurs

Le lecteur mesure le temps pendant lequel l’audio joue vraiment, pauses exclues, et l’envoie avec la progression. Chacun voit ses propres chiffres ; en tant qu’admin, je vois ceux de tout le monde. Le contrôle est fait côté serveur : un compte ne peut pas demander les statistiques d’un autre.

Comptes et sécurité

Page d'administration : comptes en attente avec boutons Valider et Refuser, comptes validés avec bouton Révoquer
MesureDétail
Mots de passeHachés avec scrypt, un sel par compte
SessionCookie HttpOnly, SameSite=Lax et Secure, valable 30 jours
Force bruteBlocage de 15 minutes après 5 mauvais mots de passe
Fichiers servisUniquement public/ : base et code source inaccessibles
IsolationChaque requête vérifie le propriétaire du livre
RévocationSupprime les sessions : déconnexion immédiate

Hébergement

Le service tourne dans un conteneur LXC Debian non privilégié, sous un utilisateur dédié. L’unité systemd le redémarre en cas de plantage et le confine : le code est en lecture seule, seul le dossier des données reste modifiable. Tailscale tourne dans le conteneur et publie le site en HTTPS avec Funnel.

Page de lecture sur téléphone, phrase en cours surlignée

Le dépôt contient le code, les captures et le guide d’installation.