Voicebar
A voice-first keyboard for Android that works alongside Gboard. Tap Voice, talk, and a tidy message lands in the box.
2-up Studio - imposition PDF (2 pages paysage par feuille portrait) + Suivi des lives. Flask + PyMuPDF.
Translation pending
ProductivityPython · JavaScriptGitHub @waelbenarfiOnlineOwner unconfirmed
Have you tried it? One tap is enough. No sign-in needed.
No updates detected yet. GitHub releases will appear here.
Owners of public repositories under a personal GitHub account can sign in to verify ownership and manage the introduction themselves. No administrator approval is needed.
Sign in, generate a verification file, and commit it to this repository’s default branch within 30 minutes. Files on other branches or forks do not count. Then check the file below to manage the project without administrator approval. Keep the file to retain your access.
If needed, you will go to sign-in. After signing in, return here and press your chosen verification button again.
Run /nomorevibe verify in your project folder to verify ownership and manage the introduction yourself.
Verify in one minuteAsk about other verification options
The maker's introduction consists of the line above. Read the repository README for more details. Repository README ↗
Loading the full README.
Read the full README ↗Application locale à deux fonctions, servies par le même serveur :
/) — deux pages paysage sur chaque feuille portrait, avec
suppression automatique des pages vides et remplacement de la première page./operations) — rapport obligatoire après chaque
séance, étapes à cocher pour chaque live (appel du professeur, fichiers,
ouverture, contrôle) avec un fil de commentaires par étape, classement
automatique des dossiers par mois, planification, support technique et
tableau de bord.
Voir SUIVI-DES-LIVES.md.Tout se passe en local, aucun fichier ne quitte la machine.
cd /d D:\pdf-2up-studio
python app.py
puis ouvrir http://localhost:1200 (ou double-cliquer sur start.bat).
Installation des dépendances (une seule fois) : pip install -r requirements.txt
Glisser le ou les PDF paysage dans la zone 1 (ou n'importe où sur la page). Plusieurs fichiers sont assemblés bout à bout dans l'ordre de la liste, et la suite du traitement se fait sur ce document unique. Le serveur rend chaque page en vignette et mesure l'encre « ajoutée » par rapport au gabarit répété du document (bandeaux, logo, filigrane).
La liste se retouche à tout moment sans rien renvoyer : + Ajouter des PDF, flèches ↑ ↓ pour changer l'ordre, × pour retirer un document. Chaque modification refusionne et réanalyse le document. Dans la grille, un séparateur rappelle où commence chaque fichier d'origine.
Vérifier les pages vides : elles apparaissent barrées en rouge dans la grille. Le curseur Sensibilité ajuste le seuil en direct, un clic sur une vignette force la conservation ou la suppression d'une page.
Nouvelle 1re page (facultatif) : un PDF ou une image remplace la page 1. Placement en couverture pleine page ou intégrée au flux 2-up.
Mise en page : format de feuille (A4, Letter, Legal, A3, A5, auto, sur mesure), marge extérieure, espace central, marge de couverture.
Générer → aperçu des feuilles produites puis Télécharger.
Le format Auto calcule une feuille exactement aux dimensions de la source
empilée deux fois : aucune bande blanche, aucune déformation.
| Fichier | Rôle |
|---|---|
app.py | serveur Flask, port 1200, API upload / assemblage / analyse / génération / téléchargement |
core.py | traitement PDF : fusion, détection des pages vides, imposition, vignettes |
templates/index.html | interface de l'outil 2-up |
static/style.css | palette Wael Academy + thème clair / sombre (partagé avec l'Espace technique) |
static/wael/ | emblème et marque Wael Academy (SVG en currentColor) |
static/app.js | logique de l'interface 2-up |
suivi/ | Espace technique : base SQLite, règles, API, PDF, archive |
templates/suivi.html, static/suivi.css, static/suivi/ | interface de l'Espace technique |
static/suivi/icones.js | jeu d'icônes tracées, à la place des émojis |
donnees-suivi/ | base et archives de l'Espace technique (créé au 1er démarrage) |
Les fichiers envoyés sont stockés dans %TEMP%\pdf-2up-studio et purgés
automatiquement au bout de 6 heures (ou en cliquant sur « Nouveau document »).
Un dossier de travail contient parts/ (les PDF d'origine, conservés tels
quels), parts.json (leur ordre), src_….pdf (le document assemblé, seul
fichier analysé et imposé) et out_….pdf (le résultat).
vercel.json déploie l'application sur Vercel : app.py y sert directement de
fonction serverless.
L'Espace technique fonctionne sur deux moteurs, choisis à l'exécution :
DATABASE_URL | moteur | usage |
|---|---|---|
| absente | SQLite, fichier local | poste de travail |
| définie | PostgreSQL | hébergement, où le disque ne survit pas |
Le reste du code écrit ses requêtes en style SQLite (placeholders ?) et ignore
lequel des deux répond : suivi/db.py traduit. Rien d'autre à changer pour
passer de l'un à l'autre.
En ligne, la variable se règle dans Vercel → Settings → Environment Variables
(nom DATABASE_URL, les trois environnements). Elle n'a rien à faire dans le
dépôt : c'est un mot de passe.
/api/suivi/etat indique quel moteur répond et les volumes en base — de quoi
vérifier après un déploiement que la variable a bien été prise en compte.
Il est désactivé. Une base neuve reste vide, prête pour vos vraies données :
aucune donnée inventée ne s'écrit jamais toute seule, et le bouton qui les
régénérait a été retiré du menu. POST /api/suivi/demo répond 403.
Pour le réactiver le temps d'une capture d'écran, poser SUIVI_DEMO=1.
Pour transférer une base locale existante vers PostgreSQL :
set DATABASE_URL=postgresql://...
python outils\migrer_vers_postgres.py
Les identifiants et les liens entre tables sont conservés, et les séquences
recalées. --remplacer écrase une cible déjà peuplée.
DATABASE_URL, la base bascule dans /tmp (détection via la variable
VERCEL) et disparaît à chaque démarrage à froid. Les pièces jointes des
rapports et des tickets, elles, restent des fichiers sur disque : elles ne
survivent pas non plus, quel que soit le moteur de base.SUIVI_DONNEES force au besoin l'emplacement des fichiers, par exemple vers un
volume monté.
Pour lever ces deux limites, préférer un hébergeur à disque persistant
(Render, Railway, Fly.io) : pip install -r requirements.txt puis
gunicorn app:app.
Dans core.py :
DETECT_DPI, DETECT_MAX_WIDTH — finesse / vitesse de l'analyseMIN_PAGES_FOR_TEMPLATE — en dessous, méthode simple sans gabaritPAGE_SIZES — ajouter un formatDans app.py : PORT, MAX_UPLOAD_MB (poids total d'un envoi),
MAX_SOURCE_FILES (nombre de PDF assemblables), JOB_TTL_SECONDS.