feat(reels): file d'attente persistante des rendus (reel_jobs)

L'ancienne file comptait les posts « processing » : un redémarrage pendant
un rendu la bloquait définitivement. Les rendus passent désormais par une
table reel_jobs, réservée avec FOR UPDATE SKIP LOCKED, avec heartbeat et
reprise des jobs interrompus au démarrage (2 tentatives maximum).

- Pipeline vidéo et pipeline images (Remotion) extraits des routes vers
  server/services/reels/, les routes ne font que valider (zod) et mettre en file
- Rendus d'images suivis en base au lieu d'une Map en mémoire
- storeName conservé pour les jobs mis en attente
- Publication Facebook en binaire : l'URL relative /uploads/... transmise
  auparavant n'était pas téléchargeable par Facebook
- Job en échec si toutes les pages échouent ou si la voix demandée manque
  (le service Python renseigne enfin tts_error)
- La voix choisie sur la page images est réellement utilisée
- sync-info mesure la voix Gemini avec sa clé
- Timeouts sur les appels au service FFmpeg, vignettes via execFile,
  /debug-ffmpeg protégé par la clé API, plus de voix anglaise en secours

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018Ze4bs7tpF1KGWUk6ZZSZ4
This commit is contained in:
Claude committed 2026-09-24 09:31:31 +00:00
1 parent fcbc6b706f
commit d24ab0d4b7
19 files changed
+1071 -901

No files matched your search

+7
View File
@@ -14,6 +14,7 @@ import { schedulerService } from "./services/scheduler";
import { ensureAdminUserExists } from "./init-admin";
import { startTokenCron } from "./cron";
import { migrate } from "./migrate";
import { startReelProcessing } from "./services/reels";
import { jamendoService } from "./services/jamendo";
import { ffmpegService } from "./services/ffmpeg";
@@ -230,5 +231,11 @@ app.use((req, res, next) => {
// Start Token Refresh Cron
startTokenCron();
// File des rendus de Reels : démarrée une fois le serveur à l'écoute, car
// le rendu d'images lit la voix et la musique via http://localhost.
startReelProcessing().catch((error) => {
console.error("❌ Démarrage de la file des Reels impossible :", error);
});
});
})();