mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-24 15:38:10 +02:00
feat(reels): montage Remotion unifié, aperçu en direct, tests et CI
Montage (étape 3) : - Nouvelle composition ReelVideo : sous-titres animés mot à mot (3 styles : Impact, Surligné, Épuré), logo, effet de fin et fondu, en React - Le service Python prépare l'image (recadrage, HDR, stabilisation, dernière image figée) et la piste son finale (/prepare-reel) ; Remotion compose - Reels d'images sur les mêmes composants, avec le vrai minutage de la voix - Police Montserrat embarquée (plus de dépendance à Google Fonts) - REEL_RENDERER=ffmpeg conserve le rendu FFmpeg, plus rapide, en secours - Script de pré-bundle réparé (échouait en silence : require en ESM) Interface (étape 4) : - Aperçu en direct avec @remotion/player, identique au rendu final ; la voix testée cale les sous-titres, sinon minutage estimé - Choix du style de sous-titres sur les 4 pages Reel - Vraie progression : étape réelle du rendu, échecs visibles 24 h avec leur cause ; fin de la barre simulée et du faux « publié avec succès » Outillage (étape 5) : - Tests vitest (minutage identique à Python, validation, sécurité) et pytest ; CI GitHub Actions (tsc, tests, build, ruff) - Captures d'écran, out.mp4 et scripts de test retirés de la racine Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018Ze4bs7tpF1KGWUk6ZZSZ4
This commit is contained in:
64 files changed
+2488
-782
No files matched your search
@@ -8,7 +8,8 @@ import { storage } from '../storage';
|
||||
import { ffmpegService, FFmpegServiceError } from '../services/ffmpeg';
|
||||
import { ttsPreviewSchema, videoReelParamsSchema, type VideoReelParams } from '@shared/reel';
|
||||
import { enqueueReelJob, countActiveReelJobs } from '../services/reels/queue';
|
||||
import { resolveGeminiApiKey, resolveStoreName } from '../services/reels/assets';
|
||||
import { resolveGeminiApiKey, resolveLogoPath, resolveStoreName } from '../services/reels/assets';
|
||||
import { configuredRenderer } from '../services/reels/videoPipeline';
|
||||
import { openRouterService, describeGenerationError } from '../services/openrouter';
|
||||
|
||||
import { estimateVoiceTiming } from '../services/ttsSync';
|
||||
@@ -378,12 +379,18 @@ reelsRouter.post('/reels', async (req: Request, res: Response) => {
|
||||
*/
|
||||
reelsRouter.get('/reels/config', async (req: Request, res: Response) => {
|
||||
try {
|
||||
const ffmpegConfigured = await ffmpegService.healthCheck().catch(() => false);
|
||||
const [ffmpegConfigured, logoUrl] = await Promise.all([
|
||||
ffmpegService.healthCheck().catch(() => false),
|
||||
resolveLogoPath(),
|
||||
]);
|
||||
|
||||
res.json({
|
||||
jamendo: { configured: false },
|
||||
freesound: { configured: false },
|
||||
ffmpeg: { configured: ffmpegConfigured },
|
||||
// Aperçu : logo affiché par le lecteur, moteur de rendu utilisé
|
||||
logoUrl: logoUrl ?? null,
|
||||
renderer: configuredRenderer(),
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('❌ Error fetching Reels config:', error);
|
||||
|
||||
@@ -74,6 +74,7 @@ remotionRouter.post("/render", upload.fields([{ name: "images", maxCount: 4 }, {
|
||||
ttsEngine: req.body.ttsEngine || undefined,
|
||||
ttsVoice: req.body.ttsVoice,
|
||||
ttsStyle: req.body.ttsStyle || undefined,
|
||||
captionStyle: req.body.captionStyle || undefined,
|
||||
storeName: await resolveStoreName(user.id, req.body.selectedPageId),
|
||||
tempFiles: uploaded.map((f) => f.path),
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user