mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-21 22:18:12 +02:00
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:
19 files changed
+1071
-901
No files matched your search
@@ -46,7 +46,9 @@ run_diagnostics()
|
||||
|
||||
|
||||
@app.get("/debug-ffmpeg")
|
||||
async def debug_ffmpeg():
|
||||
async def debug_ffmpeg(x_api_key: str = Header(None)):
|
||||
if x_api_key != API_KEY:
|
||||
raise HTTPException(status_code=401, detail="Invalid API Key")
|
||||
try:
|
||||
filters = subprocess.run(
|
||||
["ffmpeg", "-filters"], capture_output=True, text=True
|
||||
@@ -57,7 +59,6 @@ async def debug_ffmpeg():
|
||||
"subtitles": "subtitles" in filters,
|
||||
"drawtext": "drawtext" in filters,
|
||||
},
|
||||
"env": {k: v for k, v in os.environ.items() if "API" not in k},
|
||||
"fonts": fonts.splitlines()[:50], # First 50
|
||||
"raw_filters_hint": filters[:500],
|
||||
}
|
||||
@@ -337,7 +338,6 @@ async def generate_tts_with_subs(
|
||||
"fr-FR-DeniseNeural",
|
||||
]
|
||||
|
||||
fallback_voices.append("en-US-JennyNeural")
|
||||
fallback_voices = list(dict.fromkeys(fallback_voices))
|
||||
|
||||
last_error = None
|
||||
@@ -902,6 +902,7 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
|
||||
|
||||
# 3. Generate TTS (if enabled)
|
||||
has_tts = False
|
||||
tts_error = None
|
||||
tts_clean_text = ""
|
||||
|
||||
if request.tts_enabled and request.text:
|
||||
@@ -966,12 +967,14 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
|
||||
has_tts = True
|
||||
else:
|
||||
print("❌ TTS audio file missing or empty!")
|
||||
tts_error = "Fichier audio de la voix vide"
|
||||
else:
|
||||
print("⚠️ TTS text is empty after cleaning, skipping.")
|
||||
except Exception as e:
|
||||
import traceback
|
||||
print(f"❌ Failed to generate TTS: {e}")
|
||||
traceback.print_exc()
|
||||
tts_error = str(e) or type(e).__name__
|
||||
|
||||
stats["tts_duration"] = time.time() - start_step
|
||||
start_step = time.time()
|
||||
@@ -1298,6 +1301,7 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
|
||||
"output_base64": out_b64,
|
||||
"duration": duration,
|
||||
"processing_stats": stats,
|
||||
"tts_error": tts_error,
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
|
||||
Reference in new issue
Block a user