feat(reels): optimize quality to 1080p, increase text size to 64, and add stabilization toggle

This commit is contained in:
Michael committed 2026-01-23 17:19:32 +01:00
1 parent f95f400202
commit 7223bbbfb2
5 files changed
+51 -50

No files matched your search

+25 -3
View File
@@ -76,6 +76,9 @@ export default function MobileNewReel() {
// État audio preview
const [isPlaying, setIsPlaying] = useState<string | null>(null);
const [musicOffset, setMusicOffset] = useState(0);
const [stabilize, setStabilize] = useState(true); // Activé par défaut pour les Reels
const [force1080p, setForce1080p] = useState(true); // Activé par défaut
const { data: pages = [] } = useQuery<SocialPage[]>({
queryKey: ['/api/pages'],
@@ -209,6 +212,7 @@ export default function MobileNewReel() {
pageIds: selectedPages,
scheduledFor: scheduledDate?.toISOString(),
musicVolume: musicVolume[0] / 100,
stabilize: stabilize,
});
};
@@ -293,9 +297,27 @@ export default function MobileNewReel() {
</div>
{selectedVideo && (
<Button className="w-full h-12 text-lg sticky bottom-4 shadow-xl" onClick={goNext}>
Suivant <ChevronRight className="ml-2 w-5 h-5" />
</Button>
<div className="space-y-3">
<Card>
<CardContent className="p-4 space-y-4">
<div className="flex items-center justify-between">
<div className="space-y-0.5">
<div className="text-sm font-medium flex items-center gap-2">
<Sparkles className="w-4 h-4 text-primary" /> Stabilisation & Qualité 1080p
</div>
<div className="text-xs text-muted-foreground">Recommandé pour Facebook Reels</div>
</div>
<Checkbox
checked={stabilize}
onCheckedChange={(checked) => setStabilize(!!checked)}
/>
</div>
</CardContent>
</Card>
<Button className="w-full h-12 text-lg sticky bottom-4 shadow-xl" onClick={goNext}>
Suivant <ChevronRight className="ml-2 w-5 h-5" />
</Button>
</div>
)}
</div>
)}
+16 -43
View File
@@ -31,7 +31,7 @@ class ReelRequest(BaseModel):
music_id: Optional[str] = None
music_url: Optional[str] = None
word_duration: float = 0.6
font_size: int = 10
font_size: int = 64
music_volume: float = 0.25
tts_enabled: bool = False
tts_voice: str = "fr-FR-VivienneMultilingualNeural"
@@ -359,7 +359,8 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
if has_tts:
# Use subtitles filter
# Force style to look like TikTok/Reels text (No Black Box, just Outline)
style = f"FontName=Arial,FontSize={request.font_size},PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,BorderStyle=1,Outline=3,Shadow=0,Bold=1,Alignment=2,MarginV=150"
# Bigger font size (64 by default) and better vertical margin for 1080p
style = f"FontName=Arial,FontSize={request.font_size},PrimaryColour=&H00FFFFFF,OutlineColour=&H00000000,BorderStyle=1,Outline=3,Shadow=0,Bold=1,Alignment=2,MarginV=300"
# Escape path for FFmpeg filter
vtt_path_str = str(tts_vtt_path).replace("\\", "/").replace(":", "\\:")
video_filters.append(
@@ -367,16 +368,12 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
)
else:
# Standard Drawtext logic
# Scale font for 1080p
sanitized_text = request.text.replace("'", "").replace(":", "\\:")
drawtext = f"drawtext=fontfile={FONT_PATH}:text='{sanitized_text}':fontcolor=white:fontsize={request.font_size}:borderw=3:bordercolor=black:x=(w-text_w)/2:y=h-text_h-150"
drawtext = f"drawtext=fontfile={FONT_PATH}:text='{sanitized_text}':fontcolor=white:fontsize={request.font_size}:borderw=3:bordercolor=black:x=(w-text_w)/2:y=h-text_h-300"
video_filters.append(drawtext)
# Audio Mixing Strategy
# We need to mix:
# 1. Original Video Audio (0:a) - if exists
# 2. Background Music (1:a) - if has_music
# 3. TTS Voice (1:a or 2:a) - if has_tts
# Detect if original video has audio
has_original_audio = False
try:
@@ -400,67 +397,43 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
filter_complex_parts = []
mix_inputs = 0
if has_music:
cmd.extend(["-i", str(input_audio_path)])
if has_tts:
cmd.extend(["-i", str(tts_audio_path)])
# Prepare inputs for mixing
# ALWAYS ignore original video audio - only use music and/or TTS
# (Original audio is never used per user request)
if has_music:
# Music volume - ensure it's properly scaled (0.0 to 1.0)
# Apply volume more aggressively for noticeable effect
music_vol = request.music_volume
if has_tts:
# Reduce music even more when TTS is active so voice is clear
music_vol = music_vol * 0.3
print(
f"🎵 Music volume applied: {music_vol:.2f} (requested: {request.music_volume})"
)
filter_complex_parts.append(f"[1:a]volume={music_vol}[a1]")
mix_inputs += 1
if has_tts:
tts_idx = 2 if has_music else 1
# Voice needs to be loud and clear
filter_complex_parts.append(f"[{tts_idx}:a]volume=1.5[a2]")
mix_inputs += 1
# Build mix command
if mix_inputs > 0:
inputs_str = ""
# Note: Original audio is never mixed in (always muted)
if has_music:
inputs_str += "[a1]"
if has_tts:
inputs_str += "[a2]"
# IMPORTANT: normalize=0 prevents amix from auto-adjusting volumes
# which was causing volume slider to have no effect
inputs_str = "".join(
["[a1]" if has_music else "", "[a2]" if has_tts else ""]
)
filter_complex_parts.append(
f"{inputs_str}amix=inputs={mix_inputs}:duration=first:dropout_transition=2:normalize=0[aout]"
)
cmd.extend(["-filter_complex", ";".join(filter_complex_parts)])
# Map processed video and audio
cmd.extend(["-map", "0:v", "-map", "[aout]"])
else:
# No audio at all, just video
cmd.extend(["-map", "0:v"])
# Apply Video Filters if any
# Scaling to 1080x1920 (Vertical HD Reel Format)
# unsharp is added to counteract any blurring from scaling
format_filter = "scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,unsharp=5:5:0.8:3:3:0.4"
video_filters.insert(0, format_filter)
if video_filters:
cmd.extend(["-vf", ",".join(video_filters)])
# -shortest not needed with duration=first in amix, but good practice if logic changes
# actually duration=first in amix takes the length of the first input (usually video audio or music if mapped first)
# We want the video length to dictate.
# Easier: just use -shortest to cut audio to video length
cmd.extend(["-shortest"])
# Quality settings
@@ -469,15 +442,15 @@ async def process_reel(request: ReelRequest, x_api_key: str = Header(None)):
"-c:v",
"libx264",
"-preset",
"medium",
"slow",
"-crf",
"18", # High quality output (lower = better, 18 is visually lossless)
"17",
"-c:a",
"aac",
"-b:a",
"192k",
"-pix_fmt",
"yuv420p", # Ensure compatibility
"yuv420p",
"-movflags",
"+faststart",
]
+2 -2
View File
@@ -185,7 +185,7 @@ reelsRouter.post('/reels/preview', async (req: Request, res: Response) => {
ttsEnabled,
ttsVoice,
wordDuration = 0.6,
fontSize = 16,
fontSize = 64,
musicVolume = 0.25,
drawText = true,
stabilize = false,
@@ -281,7 +281,7 @@ reelsRouter.post('/reels', async (req: Request, res: Response) => {
pageIds,
scheduledFor,
wordDuration = 0.6,
fontSize = 16,
fontSize = 64,
musicVolume = 0.25,
drawText = true,
stabilize = false,
+2 -2
View File
@@ -85,7 +85,7 @@ export class FFmpegService {
tts_enabled: options.ttsEnabled,
tts_voice: options.ttsVoice,
word_duration: options.wordDuration ?? 0.6,
font_size: options.fontSize ?? 16,
font_size: options.fontSize ?? 64,
music_volume: options.musicVolume ?? 0.25,
draw_text: options.drawText ?? true,
stabilize: options.stabilize ?? false,
@@ -180,7 +180,7 @@ export class FFmpegService {
tts_enabled: options.ttsEnabled,
tts_voice: options.ttsVoice,
word_duration: options.wordDuration ?? 0.6,
font_size: options.fontSize ?? 16,
font_size: options.fontSize ?? 64,
music_volume: options.musicVolume ?? 0.25,
draw_text: options.drawText ?? true,
stabilize: options.stabilize ?? false,
+6
View File
@@ -102,6 +102,12 @@ Ajout d'une fonctionnalité complète de création de Reels Facebook permettant
- [x] **Fix API 500** (`server/routes/reels.ts`) : Variable `stabilize` manquante corrigée.
- [x] **Fix iOS Upload** (`client/src/pages/new-reel.tsx`) : Ajout support `.mov` et augmentation limite taille (500MB).
- [ ] **Support Gros Fichiers (4GB)** : Passage à DiskStorage et streaming Cloudinary.
- [ ] **Phase 10: Optimisation 1080p & Qualité Maximale** ⏳
- [x] FFmpeg: Forcer scaling 1080x1920 (Vertical HD)
- [x] FFmpeg: Augmenter CRF à 17 et preset à `slow`
- [x] FFmpeg: Augmenter taille police par défaut à 64
- [x] FFmpeg: Positionner texte plus bas (proportionnel 1080p)
- [/] Frontend: Ajouter toggle Stabilisation et Qualité
## Progress Log